VintaSoft Imaging .NET SDK 14.0: Документация для .NET разработчика
В этом разделе
    Пример пользовательского кодека
    В этом разделе
    Приведенная ниже серия примеров демонстрирует, как:

    Пример класса SimpleBmpCodec, производного от класса кодека

    Вот C#/VB.NET код, который демонстрирует, как создать класс SimpleBmpCodec, производный от класса Codec:
    public class SimpleBmpCodec : Vintasoft.Imaging.Codecs.Codec
    {
    
        #region Constructor
    
        /// <summary>
        /// Initializes a new instance of the SimpleBmpCodec class.
        /// </summary>
        public SimpleBmpCodec()
            : base("Simple Bmp", ".bmp")
        {
        }
    
        #endregion
    
    
    
        #region Properties
    
        /// <summary>
        /// Gets a value indicating whether codec can create decoder.
        /// </summary>
        /// <value>
        /// Always returns <b>true</b>.
        /// </value>
        public override bool CanCreateDecoder
        {
            get { return true; }
        }
    
        /// <summary>
        /// Gets a value indicating whether codec can create encoder.
        /// </summary>
        /// <value>
        /// Always returns <b>true</b>.
        /// </value>
        public override bool CanCreateEncoder
        {
            get { return true; }
        }
    
        #endregion
    
    
    
        #region Methods
    
        /// <summary>
        /// Creates a new decoder instance for decoding specified stream.
        /// </summary>
        /// <param name="stream">A stream which should be opened using decoder.</param>
        /// <param name="layoutSettings">A document layout settings.</param>
        /// <returns>New decoder instance for specified stream.</returns>
        public override Vintasoft.Imaging.Codecs.Decoders.DecoderBase CreateDecoder(System.IO.Stream stream,
            Vintasoft.Imaging.Codecs.Decoders.DocumentLayoutSettings layoutSettings)
        {
            return new SimpleBmpDecoder(stream);
        }
    
        /// <summary>
        /// Creates a new decoder instance of the codec.
        /// </summary>
        /// <returns>New decoder instance.</returns>
        public override Vintasoft.Imaging.Codecs.Decoders.DecoderBase CreateDecoder()
        {
            return new SimpleBmpDecoder();
        }
    
        /// <summary>
        /// Creates a new encoder instance of the codec.
        /// </summary>
        /// <returns>New encoder instance.</returns>
        public override Vintasoft.Imaging.Codecs.Encoders.EncoderBase CreateEncoder()
        {
            return new SimpleBmpEncoder();
        }
    
        #endregion
    
    }
    
    Public Class SimpleBmpCodec
        Inherits Vintasoft.Imaging.Codecs.Codec
    
        #Region "Constructor"
    
        ''' <summary>
        ''' Initializes a new instance of the SimpleBmpCodec class.
        ''' </summary>
        Public Sub New()
            MyBase.New("Simple Bmp", ".bmp")
        End Sub
    
        #End Region
    
    
    
        #Region "Properties"
    
        ''' <summary>
        ''' Gets a value indicating whether codec can create decoder.
        ''' </summary>
        ''' <value>
        ''' Always returns <b>true</b>.
        ''' </value>
        Public Overrides ReadOnly Property CanCreateDecoder() As Boolean
            Get
                Return True
            End Get
        End Property
    
        ''' <summary>
        ''' Gets a value indicating whether codec can create encoder.
        ''' </summary>
        ''' <value>
        ''' Always returns <b>true</b>.
        ''' </value>
        Public Overrides ReadOnly Property CanCreateEncoder() As Boolean
            Get
                Return True
            End Get
        End Property
    
        #End Region
    
    
    
        #Region "Methods"
    
        ''' <summary>
        ''' Creates a new decoder instance for decoding specified stream.
        ''' </summary>
        ''' <param name="stream">A stream which should be opened using decoder.</param>
        ''' <param name="layoutSettings">A document layout settings.</param>
        ''' <returns>New decoder instance for specified stream.</returns>
        Public Overrides Function CreateDecoder(stream As System.IO.Stream, layoutSettings As Vintasoft.Imaging.Codecs.Decoders.DocumentLayoutSettings) As Vintasoft.Imaging.Codecs.Decoders.DecoderBase
            Return New SimpleBmpDecoder(stream)
        End Function
    
        ''' <summary>
        ''' Creates a new decoder instance of the codec.
        ''' </summary>
        ''' <returns>New decoder instance.</returns>
        Public Overrides Function CreateDecoder() As Vintasoft.Imaging.Codecs.Decoders.DecoderBase
            Return New SimpleBmpDecoder()
        End Function
    
        ''' <summary>
        ''' Creates a new encoder instance of the codec.
        ''' </summary>
        ''' <returns>New encoder instance.</returns>
        Public Overrides Function CreateEncoder() As Vintasoft.Imaging.Codecs.Encoders.EncoderBase
            Return New SimpleBmpEncoder()
        End Function
    
        #End Region
    
    End Class
    



    Пример метода, который демонстрирует, как использовать класс SimpleBmpCodec вместо стандартного BMP кодека

    Вот C#/VB.NET код, который демонстрирует, как использовать класс SimpleBmpCodec вместо стандартного BMP кодека:
    /// <summary>
    /// Replaces the standard BMP codec to the simple BMP codec.
    /// </summary>
    public static void ReplaceStandardBmpCodecToSimpleBmpCodec()
    {
        Vintasoft.Imaging.Codecs.Codec standardBmpCodec = null;
        // search a reference to the standard BMP codec
        for (int i = 0; i < Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs.Count; i++)
        {
            if (Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs[i].Name.ToUpperInvariant() == "BMP")
            {
                standardBmpCodec = Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs[i];
                break;
            }
        }
        // remove standard BMP codec
        Vintasoft.Imaging.Codecs.AvailableCodecs.RemoveCodec(standardBmpCodec);
        // add simple BMP codec
        Vintasoft.Imaging.Codecs.AvailableCodecs.AddCodec(new SimpleBmpCodec());
    }
    
    /// <summary>
    /// Replaces the simple BMP codec to the standard BMP codec.
    /// </summary>
    public static void ReplaceSimpleBmpCodecToStandardBmpCodec()
    {
        Vintasoft.Imaging.Codecs.Codec simpleBmpCodec = null;
        // search a reference to the simple BMP codec
        for (int i = 0; i < Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs.Count; i++)
        {
            if (Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs[i].Name.ToUpperInvariant() == "SIMPLE BMP")
            {
                simpleBmpCodec = Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs[i];
                break;
            }
        }
        // remove simple BMP codec
        Vintasoft.Imaging.Codecs.AvailableCodecs.RemoveCodec(simpleBmpCodec);
        // add standard BMP codec
        Vintasoft.Imaging.Codecs.AvailableCodecs.AddCodec(Vintasoft.Imaging.Codecs.Codec.CreateStandardCodec("Bmp"));
    }
    
    ''' <summary>
    ''' Replaces the standard BMP codec to the simple BMP codec.
    ''' </summary>
    Public Shared Sub ReplaceStandardBmpCodecToSimpleBmpCodec()
        Dim standardBmpCodec As Vintasoft.Imaging.Codecs.Codec = Nothing
        ' search a reference to the standard BMP codec
        For i As Integer = 0 To Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs.Count - 1
            If Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs(i).Name.ToUpperInvariant() = "BMP" Then
                standardBmpCodec = Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs(i)
                Exit For
            End If
        Next
        ' remove standard BMP codec
        Vintasoft.Imaging.Codecs.AvailableCodecs.RemoveCodec(standardBmpCodec)
        ' add simple BMP codec
        Vintasoft.Imaging.Codecs.AvailableCodecs.AddCodec(New SimpleBmpCodec())
    End Sub
    
    ''' <summary>
    ''' Replaces the simple BMP codec to the standard BMP codec.
    ''' </summary>
    Public Shared Sub ReplaceSimpleBmpCodecToStandardBmpCodec()
        Dim simpleBmpCodec As Vintasoft.Imaging.Codecs.Codec = Nothing
        ' search a reference to the simple BMP codec
        For i As Integer = 0 To Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs.Count - 1
            If Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs(i).Name.ToUpperInvariant() = "SIMPLE BMP" Then
                simpleBmpCodec = Vintasoft.Imaging.Codecs.AvailableCodecs.Codecs(i)
                Exit For
            End If
        Next
        ' remove simple BMP codec
        Vintasoft.Imaging.Codecs.AvailableCodecs.RemoveCodec(simpleBmpCodec)
        ' add standard BMP codec
        Vintasoft.Imaging.Codecs.AvailableCodecs.AddCodec(Vintasoft.Imaging.Codecs.Codec.CreateStandardCodec("Bmp"))
    End Sub
    



    Пример декодера для кодека SimpleBmp

    Вот C#/VB.NET код, который демонстрирует, как создать декодер для кодека SimpleBmp:
    /// <summary>
    /// Defines a decoder for BMP images.
    /// </summary>
    public class SimpleBmpDecoder : Vintasoft.Imaging.Codecs.Decoders.DecoderBase
    {
    
        #region Fields
    
        /// <summary>
        /// BMP file.
        /// </summary>
        SimpleBmpFile _file = null;
    
        #endregion
    
    
    
        #region Constructor
    
        /// <summary>
        /// Initializes a new instance of the <see cref="SimpleBmpDecoder"/> class.
        /// </summary>
        public SimpleBmpDecoder()
            : base()
        {
        }
    
        /// <summary>
        /// Initializes a new instance of the <see cref="SimpleBmpDecoder"/> class.
        /// </summary>
        /// <param name="stream">Stream with the image.</param>
        public SimpleBmpDecoder(System.IO.Stream stream)
            : base(stream)
        {
            _file = new SimpleBmpFile(stream);
        }
    
        #endregion
    
    
    
        #region Properties
    
        /// <summary>
        /// Gets the name of the decoder.
        /// </summary>
        public override string Name
        {
            get
            {
                return "Simple Bmp";
            }
        }
    
        #endregion
    
    
    
        #region Methods
    
        /// <summary>
        /// Determines that stream contains image file in format of this decoder.
        /// </summary>
        /// <param name="stream">Stream with binary data of the image file.</param>
        /// <returns>
        /// <b>true</b> if stream contains image file in format of this decoder;
        /// otherwise, <b>false</b>.
        /// </returns>
        public override bool IsValidFormat(System.IO.Stream stream)
        {
            lock (stream)
                return SimpleBmpFile.IsValidFormat(stream);
        }
    
        /// <summary>
        /// Returns information about BMP image without loading the image data into memory.
        /// </summary>
        /// <param name="pageIndex">The zero based page index.</param>
        /// <param name="renderingSettings">Rendering settings used for getting info about
        /// the image of page.</param>
        /// <param name="decodingSettings">decoding settings used for getting info about
        /// the image of page.</param>
        /// <returns>Information about the image associated with the
        /// page of the source image.</returns>
        public override Vintasoft.Imaging.Codecs.Decoders.ImageInfo GetImageInfo(
            int pageIndex, 
            Vintasoft.Imaging.Codecs.Decoders.RenderingSettings renderingSettings, 
            Vintasoft.Imaging.Codecs.Decoders.DecodingSettings decodingSettings)
        {
            CheckPageIndexValue(pageIndex);
            CheckRenderingSettingsValue(renderingSettings);
    
            SimpleBmpPage page = _file.Page;
            Vintasoft.Imaging.Palette palette = page.Palette;
            if (palette == null)
                palette = new Vintasoft.Imaging.Palette();
    
            return new Vintasoft.Imaging.Codecs.Decoders.ImageInfo(
                page.Width, page.Height, page.PixelFormat, palette, page.Resolution);
        }
    
        /// <summary>
        /// Returns an image of BMP file.
        /// </summary>
        /// <param name="pageIndex">The zero based page index (is not used).</param>
        /// <param name="decodingSettings">Decoding settings used for decode the image of page.</param>
        /// <param name="renderingSettings">Rendering settings used for rendering the image
        /// of page (is not used).</param>
        /// <param name="progressDelegate">Progress delegate.</param>
        /// <returns>Image of BMP file.</returns>
        public override Vintasoft.Imaging.VintasoftImage GetImage(int pageIndex,
            Vintasoft.Imaging.Codecs.Decoders.DecodingSettings decodingSettings,
            Vintasoft.Imaging.Codecs.Decoders.RenderingSettings renderingSettings,
            System.EventHandler<Vintasoft.Imaging.ProgressEventArgs> progressDelegate)
        {
            CheckPageIndexValue(pageIndex);
            CheckRenderingSettingsValue(renderingSettings);
    
            lock (_file)
            {
                // get image
                Vintasoft.Imaging.VintasoftImage image = _file.Page.GetImage(progressDelegate);
    
                // perform the color correction if necessary
                PerformColorCorrection(pageIndex, image, decodingSettings);
    
                // return the image
                return image;
            }
        }
    
        /// <summary>
        /// Returns a metadata of BMP file.
        /// </summary>
        /// <param name="pageIndex">The zero based page index (not used).</param>
        /// <returns>Metadata of BMP file.</returns>
        public override Vintasoft.Imaging.Metadata.PageMetadata GetPageMetadata(int pageIndex)
        {
            return new Vintasoft.Imaging.Metadata.PageMetadata("Bmp");
        }
    
        /// <summary>
        /// Closes the source of the decoder.
        /// </summary>
        public override void Close()
        {
            if (_file != null)
            {
                _file.Dispose();
                _file = null;
            }
            base.Close();
        }
    
        #endregion
    
    }
    
    ''' <summary>
    ''' Defines a decoder for BMP images.
    ''' </summary>
    Public Class SimpleBmpDecoder
        Inherits Vintasoft.Imaging.Codecs.Decoders.DecoderBase
    
        #Region "Fields"
    
        ''' <summary>
        ''' BMP file.
        ''' </summary>
        Private _file As SimpleBmpFile = Nothing
    
        #End Region
    
    
    
        #Region "Constructor"
    
        ''' <summary>
        ''' Initializes a new instance of the <see cref="SimpleBmpDecoder"/> class.
        ''' </summary>
        Public Sub New()
            MyBase.New()
        End Sub
    
        ''' <summary>
        ''' Initializes a new instance of the <see cref="SimpleBmpDecoder"/> class.
        ''' </summary>
        ''' <param name="stream">Stream with the image.</param>
        Public Sub New(stream As System.IO.Stream)
            MyBase.New(stream)
            _file = New SimpleBmpFile(stream)
        End Sub
    
        #End Region
    
    
    
        #Region "Properties"
    
        ''' <summary>
        ''' Gets the name of the decoder.
        ''' </summary>
        Public Overrides ReadOnly Property Name() As String
            Get
                Return "Simple Bmp"
            End Get
        End Property
    
        #End Region
    
    
    
        #Region "Methods"
    
        ''' <summary>
        ''' Determines that stream contains image file in format of this decoder.
        ''' </summary>
        ''' <param name="stream">Stream with binary data of the image file.</param>
        ''' <returns>
        ''' <b>true</b> if stream contains image file in format of this decoder;
        ''' otherwise, <b>false</b>.
        ''' </returns>
        Public Overrides Function IsValidFormat(stream As System.IO.Stream) As Boolean
            SyncLock stream
                Return SimpleBmpFile.IsValidFormat(stream)
            End SyncLock
        End Function
    
        ''' <summary>
        ''' Returns information about BMP image without loading the image data into memory.
        ''' </summary>
        ''' <param name="pageIndex">The zero based page index.</param>
        ''' <param name="renderingSettings">Rendering settings used for getting info about
        ''' the image of page.</param>
        ''' <param name="decodingSettings">decoding settings used for getting info about
        ''' the image of page.</param>
        ''' <returns>Information about the image associated with the
        ''' page of the source image.</returns>
        Public Overrides Function GetImageInfo(pageIndex As Integer, renderingSettings As Vintasoft.Imaging.Codecs.Decoders.RenderingSettings, decodingSettings As Vintasoft.Imaging.Codecs.Decoders.DecodingSettings) As Vintasoft.Imaging.Codecs.Decoders.ImageInfo
            CheckPageIndexValue(pageIndex)
            CheckRenderingSettingsValue(renderingSettings)
    
            Dim page As SimpleBmpPage = _file.Page
            Dim palette As Vintasoft.Imaging.Palette = page.Palette
            If palette Is Nothing Then
                palette = New Vintasoft.Imaging.Palette()
            End If
    
            Return New Vintasoft.Imaging.Codecs.Decoders.ImageInfo(page.Width, page.Height, page.PixelFormat, palette, page.Resolution)
        End Function
    
        ''' <summary>
        ''' Returns an image of BMP file.
        ''' </summary>
        ''' <param name="pageIndex">The zero based page index (is not used).</param>
        ''' <param name="decodingSettings">Decoding settings used for decode the image of page.</param>
        ''' <param name="renderingSettings">Rendering settings used for rendering the image
        ''' of page (is not used).</param>
        ''' <param name="progressDelegate">Progress delegate.</param>
        ''' <returns>Image of BMP file.</returns>
        Public Overrides Function GetImage(pageIndex As Integer, decodingSettings As Vintasoft.Imaging.Codecs.Decoders.DecodingSettings, renderingSettings As Vintasoft.Imaging.Codecs.Decoders.RenderingSettings, progressDelegate As System.EventHandler(Of Vintasoft.Imaging.ProgressEventArgs)) As Vintasoft.Imaging.VintasoftImage
            CheckPageIndexValue(pageIndex)
            CheckRenderingSettingsValue(renderingSettings)
    
            SyncLock _file
                ' get image
                Dim image As Vintasoft.Imaging.VintasoftImage = _file.Page.GetImage(progressDelegate)
    
                ' perform the color correction if necessary
                PerformColorCorrection(pageIndex, image, decodingSettings)
    
                ' return the image
                Return image
            End SyncLock
        End Function
    
        ''' <summary>
        ''' Returns a metadata of BMP file.
        ''' </summary>
        ''' <param name="pageIndex">The zero based page index (not used).</param>
        ''' <returns>Metadata of BMP file.</returns>
        Public Overrides Function GetPageMetadata(pageIndex As Integer) As Vintasoft.Imaging.Metadata.PageMetadata
            Return New Vintasoft.Imaging.Metadata.PageMetadata("Bmp")
        End Function
    
        ''' <summary>
        ''' Closes the source of the decoder.
        ''' </summary>
        Public Overrides Sub Close()
            If _file IsNot Nothing Then
                _file.Dispose()
                _file = Nothing
            End If
            MyBase.Close()
        End Sub
    
        #End Region
    
    End Class
    



    Пример энкодера для кодека SimpleBmp

    Вот C#/VB.NET код, который демонстрирует, как создать энкодер для кодека SimpleBmp:
    /// <summary>
    /// Defines an encoder for BMP images.
    /// </summary>
    public class SimpleBmpEncoder : Vintasoft.Imaging.Codecs.Encoders.EncoderBase
    {
                
        #region Constructor
    
        /// <summary>
        /// Initializes a new instance of the SimpleBmpEncoder class.
        /// </summary>
        public SimpleBmpEncoder() 
            : base()
        {
        }
    
        #endregion
    
    
    
        #region Properties
      
        /// <summary>
        /// Gets the name of the encoder.
        /// </summary>
        public override string Name
        {
            get 
            {
                return "Simple Bmp";
            }
        }
    
        #endregion
    
    
    
        #region Methods
    
        /// <summary>
        /// Sets the encoder settings.
        /// </summary>
        /// <param name="encoderSettings">The encoder settings.</param>
        public override void SetSettings(Vintasoft.Imaging.Codecs.Encoders.EncoderSettings encoderSettings)
        {
            throw new System.NotSupportedException();
        }
    
        /// <summary>
        /// Saves single image to the stream.
        /// </summary>
        /// <param name="image"><b>VintasoftImage</b> object to save.</param>
        /// <param name="metadataTree">Virtual metadata tree which contains information
        /// about cached image metadata.</param>
        /// <param name="stream">Stream where the image should be saved.</param>
        /// <param name="progressController">Progress controller.</param>
        protected override void SaveImageWithMetadataToStream(
            Vintasoft.Imaging.VintasoftImage image, 
            Vintasoft.Imaging.Metadata.MetadataNode metadataTree, 
            System.IO.Stream stream, 
            Vintasoft.Imaging.Utils.IProgressController progressController)
        {
            stream.SetLength(0);
    
            using (SimpleBmpFile bmpFile = new SimpleBmpFile(image))
            {
                bmpFile.Save(stream, progressController);
            }
        }
    
        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public override object Clone()
        {
            SimpleBmpEncoder encoder = new SimpleBmpEncoder();
            CopyTo(encoder);
            return encoder;
        }
    
        #endregion
    
    }
    
    ''' <summary>
    ''' Defines an encoder for BMP images.
    ''' </summary>
    Public Class SimpleBmpEncoder
        Inherits Vintasoft.Imaging.Codecs.Encoders.EncoderBase
    
        #Region "Constructor"
    
        ''' <summary>
        ''' Initializes a new instance of the SimpleBmpEncoder class.
        ''' </summary>
        Public Sub New()
            MyBase.New()
        End Sub
    
        #End Region
    
    
    
        #Region "Properties"
    
        ''' <summary>
        ''' Gets the name of the encoder.
        ''' </summary>
        Public Overrides ReadOnly Property Name() As String
            Get
                Return "Simple Bmp"
            End Get
        End Property
    
        #End Region
    
    
    
        #Region "Methods"
    
        ''' <summary>
        ''' Sets the encoder settings.
        ''' </summary>
        ''' <param name="encoderSettings">The encoder settings.</param>
        Public Overrides Sub SetSettings(encoderSettings As Vintasoft.Imaging.Codecs.Encoders.EncoderSettings)
            Throw New System.NotSupportedException()
        End Sub
    
        ''' <summary>
        ''' Saves single image to the stream.
        ''' </summary>
        ''' <param name="image"><b>VintasoftImage</b> object to save.</param>
        ''' <param name="metadataTree">Virtual metadata tree which contains information
        ''' about cached image metadata.</param>
        ''' <param name="stream">Stream where the image should be saved.</param>
        ''' <param name="progressController">Progress controller.</param>
        Protected Overrides Sub SaveImageWithMetadataToStream(image As Vintasoft.Imaging.VintasoftImage, metadataTree As Vintasoft.Imaging.Metadata.MetadataNode, stream As System.IO.Stream, progressController As Vintasoft.Imaging.Utils.IProgressController)
            stream.SetLength(0)
    
            Using bmpFile As New SimpleBmpFile(image)
                bmpFile.Save(stream, progressController)
            End Using
        End Sub
    
        ''' <summary>
        ''' Creates a new object that is a copy of the current instance.
        ''' </summary>
        ''' <returns>
        ''' A new object that is a copy of this instance.
        ''' </returns>
        Public Overrides Function Clone() As Object
            Dim encoder As New SimpleBmpEncoder()
            CopyTo(encoder)
            Return encoder
        End Function
    
        #End Region
    
    End Class
    



    Пример файла изображения для кодека SimpleBmp

    Вот C#/VB.NET код, который демонстрирует, как создать файл изображения для кодека SimpleBmp:
    /// <summary>
    /// Class that allows to manipulate BMP file.
    /// </summary>
    public class SimpleBmpFile : 
        Vintasoft.Imaging.Codecs.ImageFiles.SinglePageImageFile<SimpleBmpPage>
    {
    
        #region Fields
    
        /// <summary>
        /// Bitmap file header length.
        /// </summary>
        const uint BITMAPFILEHEADER_LENGTH = 14;
    
        /// <summary>
        /// Image data offset.
        /// </summary>
        uint _offsetToImageData;
    
        /// <summary>
        /// BMP file size.
        /// </summary>
        uint _fileSize;
    
        #endregion
    
    
    
        #region Constructor
    
        /// <summary>
        /// Initializes a new instance of the <see cref="SimpleBmpFile"/> class.
        /// </summary>
        /// <param name="stream">Stream which contains the image file.</param>
        public SimpleBmpFile(System.IO.Stream stream)
            : base(stream)
        {
            _source = new Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(stream);
            try
            {
                Parse();
            }
            catch
            {
                _source.Dispose();
                throw;
            }
        }
    
        /// <summary>
        /// Initializes a new instance of the <see cref="SimpleBmpFile"/> class.
        /// </summary>
        /// <param name="fileName">The name of the image file.</param>
        /// <param name="mode">A FileMode constant that determines how to open or create the image file.</param>
        /// <param name="access">A FileAccess constant that determines how the image file can be accessed.</param>
        public SimpleBmpFile(string fileName, System.IO.FileMode mode, System.IO.FileAccess access)
            : base(fileName, mode, access)
        {
            _source = new Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(fileName, mode, access);
            try
            {
                Parse();
            }
            catch
            {
                _source.Dispose();
                throw;
            }
        }
    
        /// <summary>
        /// Initializes a new instance of the <see cref="SimpleBmpFile"/> class.
        /// </summary>
        /// <param name="image">A first page image.</param>
        public SimpleBmpFile(Vintasoft.Imaging.VintasoftImage image)
        {
            if (image.PixelFormat != Vintasoft.Imaging.PixelFormat.Bgr24 &&
                image.PixelFormat != Vintasoft.Imaging.PixelFormat.Bgr32)
                throw new System.NotImplementedException();
    
            // create memory stream
            System.IO.MemoryStream stream = new System.IO.MemoryStream();
            // create image file source
            _source = new Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(stream);
            // create new Bmp page
            base.Page = new SimpleBmpPage(_source, image);
        }
    
        #endregion
    
    
    
        #region Properties
    
        Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource _source;
        /// <summary>
        /// Source of the image file.
        /// </summary>
        /// <remarks>
        /// This object provides access to the binary data of the image file.
        /// </remarks>
        protected override Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource Source
        {
            get
            {
                return _source;
            }
        }
    
        /// <summary>
        /// Gets the page of this BMP file.
        /// </summary>
        /// <exception cref="System.InvalidOperationException">Thrown if page is sets.</exception>
        public override SimpleBmpPage Page
        {
            get
            {
                return base.Page;
            }
            set
            {
                throw new System.InvalidOperationException();
            }
        }
    
        #endregion
    
    
    
        #region Methods
    
        #region PUBLIC
    
        /// <summary>
        /// Saves this BMP file to specified stream.
        /// </summary>
        /// <param name="stream">Stream to save the image file.</param>
        /// <param name="progressController">Progress controller.</param>
        /// <exception cref="System.ArgumentNullException">Thrown if <i>stream</i> is null.</exception>
        /// <remarks>
        /// This method saves changes to specified stream. Current source of the image
        /// file is not changed.
        /// </remarks>
        public override void Save(System.IO.Stream stream, 
            Vintasoft.Imaging.Utils.IProgressController progressController)
        {
            // create image file source
            using (Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source = 
                new Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(stream))
            {
                SaveToSource(source, progressController);
            }
        }
    
        /// <summary>
        /// Saves this BMP file to specified file.
        /// </summary>
        /// <param name="filename">The name of the image file.</param>
        /// <param name="progressController">Progress controller.</param>
        /// <exception cref="System.ArgumentNullException">Thrown if <i>filename</i> is null.</exception>
        /// <remarks>
        /// This method saves changes to specified file. Current source of the image
        /// file is not changed.
        /// </remarks>
        public override void Save(string filename, 
            Vintasoft.Imaging.Utils.IProgressController progressController)
        {
            // create image file source
            using (Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source = 
                new Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(
                filename, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite))
            {
                SaveToSource(source, progressController);
            }
        }
    
        /// <summary>
        /// Saves changes of the image file to specified stream.
        /// </summary>
        /// <param name="stream">Stream to save the image file.</param>
        /// <param name="progressController">Progress controller.</param>
        /// <remarks>
        /// This method saves changes to specified stream and makes this stream
        /// as current source of the image file. Previous source of the image
        /// file is closed without save changes.
        /// </remarks>
        public override void SaveChanges(System.IO.Stream stream, 
            Vintasoft.Imaging.Utils.IProgressController progressController)
        {
            // create image file source
            using (Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source =
                new Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(stream))
            {
                source.SwitchToThisSource = true;
                SaveToSource(source, progressController);
            }
        }
    
        /// <summary>
        /// Saves changes of the image file to specified file.
        /// </summary>
        /// <param name="filename">The filename to save the image file.</param>
        /// <param name="progressController">Progress controller.</param>
        /// <remarks>
        /// This method saves changes to specified file and makes this file
        /// as current source of the image file. Previous source of the image
        /// file is closed without save changes.
        /// </remarks>
        public override void SaveChanges(string filename, 
            Vintasoft.Imaging.Utils.IProgressController progressController)
        {
            // create image file source
            using (Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source = 
                new Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(
                filename, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite))
            {
                source.SwitchToThisSource = true;
                SaveToSource(source, progressController);
            }
        }
    
        /// <summary>
        /// Saves changes of the image file to the current source of the image file.
        /// </summary>
        /// <param name="progressController">Progress controller.</param>
        /// <exception cref="System.InvalidOperationException">
        /// Thrown if source is open in read-only mode and cannot be changed.
        /// </exception>
        public override void SaveChanges(
            Vintasoft.Imaging.Utils.IProgressController progressController)
        {
            // if can't be write to source
            if (!Source.Stream.CanWrite)
                throw new System.InvalidOperationException();
    
            Source.Position = BITMAPFILEHEADER_LENGTH;
            // update page header
            Page.WriteHeader(Source);
        }
    
        /// <summary>
        /// Determines that stream contains BMP file.
        /// </summary>
        /// <param name="stream">Stream with binary data of the BMP file.</param>
        /// <returns>
        /// <b>true</b> if stream contains BMP file;
        /// otherwise, <b>false</b>.
        /// </returns>
        public static bool IsValidFormat(System.IO.Stream stream)
        {
            long position = stream.Position;
            try
            {
                return (stream.ReadByte() == 0x42) && (stream.ReadByte() == 0x4D);
            }
            finally
            {
                stream.Position = position;
            }            
        }
    
        #endregion
    
    
        #region PROTECTED
    
        /// <summary>
        /// Parses the BMP file.
        /// </summary>
        /// <remarks>
        /// This method reads structure of the image file and must called from the
        /// constructor of the class.
        /// </remarks>
        protected override void Parse()
        {
            lock (Source.Stream)
            {
                // WORD bfType
                if (Source.ReadByte() != 0x42 || Source.ReadByte() != 0x4D)
                    throw new System.ArgumentException("ImageFileSource is not BMP file.", "Source");
    
                // DWORD bfSize
                _fileSize = Source.ReadUInt32();
    
                // WORD bfReserved1
                // WORD bfReserved2
                Source.Position += 4;
    
                // DWORD bfOffBits
                _offsetToImageData = Source.ReadUInt32();
    
                // parse page
                base.Page = new SimpleBmpPage(Source, _offsetToImageData);
            }
        }
    
        #endregion
    
    
        #region PRIVATE
    
        /// <summary>
        /// Saves BMP file to a source.
        /// </summary>
        /// <param name="source">Source of the image file.</param>
        /// <param name="progressController">Progress controller.</param>
        private void SaveToSource(
            Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source,
            Vintasoft.Imaging.Utils.IProgressController progressController)
        {
            // if specified source equals source of this file
            if (source.Stream == this.Source.Stream)
            {
                // save changes to a file
                SaveChanges(progressController);
                return;
            }
    
            // write header
            WriteHeader(source);
    
            // write page
            Page.Save(source, progressController);
    
            // if it is necessary to switch the source
            if (source.SwitchToThisSource)
            {
                // if this file has the source
                if (this.Source != null)
                    // close current source of this file
                    this.Source.Dispose();
    
                // set a new source for this file
                _source = source;
            }
        }
    
        /// <summary>
        /// Writes the BMP file header to a source.
        /// </summary>
        /// <param name="source">Source of the image file.</param>
        private void WriteHeader(Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source)
        {
            lock (source.Stream)
            {
                // WORD bfType
                source.WriteByte(0x42);
                source.WriteByte(0x4D);
                // DWORD bfSize
                source.WriteUInt32(_fileSize);
                // WORD bfReserved1
                source.WriteUInt16(0);
                // WORD bfReserved2
                source.WriteUInt16(0);
                // DWORD bfOffBits - write BMP file header length + BMP page header length
                source.WriteUInt32(BITMAPFILEHEADER_LENGTH + SimpleBmpPage.BITMAPINFOHEADER_LENGTH);
            }
        }
    
        #endregion
    
        #endregion
    
    }
    
    ''' <summary>
    ''' Class that allows to manipulate BMP file.
    ''' </summary>
    Public Class SimpleBmpFile
        Inherits Vintasoft.Imaging.Codecs.ImageFiles.SinglePageImageFile(Of SimpleBmpPage)
    
        #Region "Fields"
    
        ''' <summary>
        ''' Bitmap file header length.
        ''' </summary>
        Const BITMAPFILEHEADER_LENGTH As UInteger = 14
    
        ''' <summary>
        ''' Image data offset.
        ''' </summary>
        Private _offsetToImageData As UInteger
    
        ''' <summary>
        ''' BMP file size.
        ''' </summary>
        Private _fileSize As UInteger
    
        #End Region
    
    
    
        #Region "Constructor"
    
        ''' <summary>
        ''' Initializes a new instance of the <see cref="SimpleBmpFile"/> class.
        ''' </summary>
        ''' <param name="stream">Stream which contains the image file.</param>
        Public Sub New(stream As System.IO.Stream)
            MyBase.New(stream)
            _source = New Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(stream)
            Try
                Parse()
            Catch
                _source.Dispose()
                Throw
            End Try
        End Sub
    
        ''' <summary>
        ''' Initializes a new instance of the <see cref="SimpleBmpFile"/> class.
        ''' </summary>
        ''' <param name="fileName">The name of the image file.</param>
        ''' <param name="mode">A FileMode constant that determines how to open or create the image file.</param>
        ''' <param name="access">A FileAccess constant that determines how the image file can be accessed.</param>
        Public Sub New(fileName As String, mode As System.IO.FileMode, access As System.IO.FileAccess)
            MyBase.New(fileName, mode, access)
            _source = New Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(fileName, mode, access)
            Try
                Parse()
            Catch
                _source.Dispose()
                Throw
            End Try
        End Sub
    
        ''' <summary>
        ''' Initializes a new instance of the <see cref="SimpleBmpFile"/> class.
        ''' </summary>
        ''' <param name="image">A first page image.</param>
        Public Sub New(image As Vintasoft.Imaging.VintasoftImage)
            If image.PixelFormat <> Vintasoft.Imaging.PixelFormat.Bgr24 AndAlso image.PixelFormat <> Vintasoft.Imaging.PixelFormat.Bgr32 Then
                Throw New System.NotImplementedException()
            End If
    
            ' create memory stream
            Dim stream As New System.IO.MemoryStream()
            ' create image file source
            _source = New Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(stream)
            ' create new Bmp page
            MyBase.Page = New SimpleBmpPage(_source, image)
        End Sub
    
        #End Region
    
    
    
        #Region "Properties"
    
        Private _source As Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource
        ''' <summary>
        ''' Source of the image file.
        ''' </summary>
        ''' <remarks>
        ''' This object provides access to the binary data of the image file.
        ''' </remarks>
        Protected Overrides ReadOnly Property Source() As Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource
            Get
                Return _source
            End Get
        End Property
    
        ''' <summary>
        ''' Gets the page of this BMP file.
        ''' </summary>
        ''' <exception cref="System.InvalidOperationException">Thrown if page is sets.</exception>
        Public Overrides Property Page() As SimpleBmpPage
            Get
                Return MyBase.Page
            End Get
            Set
                Throw New System.InvalidOperationException()
            End Set
        End Property
    
        #End Region
    
    
    
        #Region "Methods"
    
        #Region "PUBLIC"
    
        ''' <summary>
        ''' Saves this BMP file to specified stream.
        ''' </summary>
        ''' <param name="stream">Stream to save the image file.</param>
        ''' <param name="progressController">Progress controller.</param>
        ''' <exception cref="System.ArgumentNullException">Thrown if <i>stream</i> is null.</exception>
        ''' <remarks>
        ''' This method saves changes to specified stream. Current source of the image
        ''' file is not changed.
        ''' </remarks>
        Public Overrides Sub Save(stream As System.IO.Stream, progressController As Vintasoft.Imaging.Utils.IProgressController)
            ' create image file source
            Using source As New Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(stream)
                SaveToSource(source, progressController)
            End Using
        End Sub
    
        ''' <summary>
        ''' Saves this BMP file to specified file.
        ''' </summary>
        ''' <param name="filename">The name of the image file.</param>
        ''' <param name="progressController">Progress controller.</param>
        ''' <exception cref="System.ArgumentNullException">Thrown if <i>filename</i> is null.</exception>
        ''' <remarks>
        ''' This method saves changes to specified file. Current source of the image
        ''' file is not changed.
        ''' </remarks>
        Public Overrides Sub Save(filename As String, progressController As Vintasoft.Imaging.Utils.IProgressController)
            ' create image file source
            Using source As New Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(filename, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite)
                SaveToSource(source, progressController)
            End Using
        End Sub
    
        ''' <summary>
        ''' Saves changes of the image file to specified stream.
        ''' </summary>
        ''' <param name="stream">Stream to save the image file.</param>
        ''' <param name="progressController">Progress controller.</param>
        ''' <remarks>
        ''' This method saves changes to specified stream and makes this stream
        ''' as current source of the image file. Previous source of the image
        ''' file is closed without save changes.
        ''' </remarks>
        Public Overrides Sub SaveChanges(stream As System.IO.Stream, progressController As Vintasoft.Imaging.Utils.IProgressController)
            ' create image file source
            Using source As New Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(stream)
                source.SwitchToThisSource = True
                SaveToSource(source, progressController)
            End Using
        End Sub
    
        ''' <summary>
        ''' Saves changes of the image file to specified file.
        ''' </summary>
        ''' <param name="filename">The filename to save the image file.</param>
        ''' <param name="progressController">Progress controller.</param>
        ''' <remarks>
        ''' This method saves changes to specified file and makes this file
        ''' as current source of the image file. Previous source of the image
        ''' file is closed without save changes.
        ''' </remarks>
        Public Overrides Sub SaveChanges(filename As String, progressController As Vintasoft.Imaging.Utils.IProgressController)
            ' create image file source
            Using source As New Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource(filename, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite)
                source.SwitchToThisSource = True
                SaveToSource(source, progressController)
            End Using
        End Sub
    
        ''' <summary>
        ''' Saves changes of the image file to the current source of the image file.
        ''' </summary>
        ''' <param name="progressController">Progress controller.</param>
        ''' <exception cref="System.InvalidOperationException">
        ''' Thrown if source is open in read-only mode and cannot be changed.
        ''' </exception>
        Public Overrides Sub SaveChanges(progressController As Vintasoft.Imaging.Utils.IProgressController)
            ' if can't be write to source
            If Not Source.Stream.CanWrite Then
                Throw New System.InvalidOperationException()
            End If
    
            Source.Position = BITMAPFILEHEADER_LENGTH
            ' update page header
            Page.WriteHeader(Source)
        End Sub
    
        ''' <summary>
        ''' Determines that stream contains BMP file.
        ''' </summary>
        ''' <param name="stream">Stream with binary data of the BMP file.</param>
        ''' <returns>
        ''' <b>true</b> if stream contains BMP file;
        ''' otherwise, <b>false</b>.
        ''' </returns>
        Public Shared Function IsValidFormat(stream As System.IO.Stream) As Boolean
            Dim position As Long = stream.Position
            Try
                Return (stream.ReadByte() = &H42) AndAlso (stream.ReadByte() = &H4d)
            Finally
                stream.Position = position
            End Try
        End Function
    
        #End Region
    
    
        #Region "PROTECTED"
    
        ''' <summary>
        ''' Parses the BMP file.
        ''' </summary>
        ''' <remarks>
        ''' This method reads structure of the image file and must called from the
        ''' constructor of the class.
        ''' </remarks>
        Protected Overrides Sub Parse()
            SyncLock Source.Stream
                ' WORD bfType
                If Source.ReadByte() <> &H42 OrElse Source.ReadByte() <> &H4d Then
                    Throw New System.ArgumentException("ImageFileSource is not BMP file.", "Source")
                End If
    
                ' DWORD bfSize
                _fileSize = Source.ReadUInt32()
    
                ' WORD bfReserved1
                ' WORD bfReserved2
                Source.Position += 4
    
                ' DWORD bfOffBits
                _offsetToImageData = Source.ReadUInt32()
    
                ' parse page
                MyBase.Page = New SimpleBmpPage(Source, _offsetToImageData)
            End SyncLock
        End Sub
    
        #End Region
    
    
        #Region "PRIVATE"
    
        ''' <summary>
        ''' Saves BMP file to a source.
        ''' </summary>
        ''' <param name="source">Source of the image file.</param>
        ''' <param name="progressController">Progress controller.</param>
        Private Sub SaveToSource(source As Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource, progressController As Vintasoft.Imaging.Utils.IProgressController)
            ' if specified source equals source of this file
            If source.Stream Is Me.Source.Stream Then
                ' save changes to a file
                SaveChanges(progressController)
                Return
            End If
    
            ' write header
            WriteHeader(source)
    
            ' write page
            Page.Save(source, progressController)
    
            ' if it is necessary to switch the source
            If source.SwitchToThisSource Then
                ' if this file has the source
                If Me.Source IsNot Nothing Then
                    ' close current source of this file
                    Me.Source.Dispose()
                End If
    
                ' set a new source for this file
                _source = source
            End If
        End Sub
    
        ''' <summary>
        ''' Writes the BMP file header to a source.
        ''' </summary>
        ''' <param name="source">Source of the image file.</param>
        Private Sub WriteHeader(source As Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource)
            SyncLock source.Stream
                ' WORD bfType
                source.WriteByte(&H42)
                source.WriteByte(&H4d)
                ' DWORD bfSize
                source.WriteUInt32(_fileSize)
                ' WORD bfReserved1
                source.WriteUInt16(0)
                ' WORD bfReserved2
                source.WriteUInt16(0)
                ' DWORD bfOffBits - write BMP file header length + BMP page header length
                source.WriteUInt32(BITMAPFILEHEADER_LENGTH + SimpleBmpPage.BITMAPINFOHEADER_LENGTH)
            End SyncLock
        End Sub
    
        #End Region
    
        #End Region
    
    End Class
    



    Пример страницы файла изображения для кодека SimpleBmp

    Вот C#/VB.NET код, который демонстрирует, как создать страницу файла изображения для кодека SimpleBmp:
    /// <summary>
    /// Class that allows to get information about BMP page.
    /// </summary>
    public class SimpleBmpPage : Vintasoft.Imaging.Codecs.ImageFiles.ImagePage
    {
    
        #region Fields
    
        /// <summary>
        /// BMP page info header length.
        /// </summary>
        internal const uint BITMAPINFOHEADER_LENGTH = 40;
    
        /// <summary>
        /// Image stride (row width in bytes).
        /// </summary>
        int _stride;
    
        /// <summary>
        /// Indicates that image raw data is reversed.
        /// </summary>
        bool _reverseReadWrite;
    
        /// <summary>
        /// Image raw data offset, in bytes.
        /// </summary>
        long _offsetToImageData;
    
        /// <summary>
        /// Image length, in bytes.
        /// </summary>
        uint _imageSize;
    
        #endregion
    
    
    
        #region Constructors
    
        /// <summary>
        /// Initializes a new instance of the <see cref="SimpleBmpPage"/> class.
        /// </summary>
        /// <param name="source">Source of the image page.</param>
        /// <param name="offset">Offset of the image page in the source.</param>
        public SimpleBmpPage(Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source, long offset)
            : base(source, offset)
        {
            _offsetToImageData = offset;
            Parse();
        }
    
        /// <summary>
        /// Initializes a new instance of the <see cref="SimpleBmpPage"/> class.
        /// </summary>
        /// <param name="source">Source of the image page.</param>
        /// <param name="image">New image.</param>
        public SimpleBmpPage(Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source, 
            Vintasoft.Imaging.VintasoftImage image)
            : base(source, 0)
        {        
            // sets the image settings
            _offsetToImageData = 0;
            _imagePixelFormat = image.PixelFormat;
            _width = image.Width;
            _height = image.Height;
            _resolution = image.Resolution;
            _hasResolution = true;
            _bitsPerPixel = image.BitsPerPixel;
    
            // calculate stride of image
            _stride = Vintasoft.Imaging.VintasoftBitmap.GetStride(_imagePixelFormat, Width);
            // image is reverse
            _reverseReadWrite = true;
    
            // encode image data
            EncodeImageData(Source, image);
    
            // set the image length
            _imageSize = (uint)Source.Length;
            // set bmp page length
            SetLength(BITMAPINFOHEADER_LENGTH + _imageSize);
        }
    
        #endregion
    
    
    
        #region Properties
    
        int _width;
        /// <summary>
        /// Gets the width, in pixels, of the image page.
        /// </summary>
        public override int Width
        {
            get
            {
                return _width;
            }
        }
    
        int _height;
        /// <summary>
        /// Gets the height, in pixels, of the image page.
        /// </summary>
        public override int Height
        {
            get
            {
                return System.Math.Abs(_height);
            }
        }
    
        int _bitsPerPixel;
        /// <summary>
        /// Gets the bit depth of the image page.
        /// </summary>
        public override int BitsPerPixel
        {
            get
            {
                return _bitsPerPixel;
            }
        }
    
        Vintasoft.Imaging.Palette _palette = null;
        /// <summary>
        /// Gets the palette of the image page.
        /// </summary>
        public override Vintasoft.Imaging.Palette Palette
        {
            get
            {
                return _palette;
            }
        }
    
        Vintasoft.Imaging.Resolution _resolution = Vintasoft.Imaging.Resolution.Empty;
        /// <summary>
        /// Gets or sets the resolution, in pixels per inch, of the image page.
        /// </summary>
        /// <value>
        /// The resolution loaded from an image metadata if <see cref="HasResolution"/> returns <b>true</b>;
        /// otherwise, the default (screen) resolution.
        /// </value>
        /// <seealso cref="HasResolution"/>
        public override Vintasoft.Imaging.Resolution Resolution
        {
            get
            {
                if (_resolution == Vintasoft.Imaging.Resolution.Empty)
                    return Vintasoft.Imaging.ImagingEnvironment.ScreenResolution;
                return _resolution;
            }
            set
            {
                throw new System.NotImplementedException();
            }
        }
    
        bool _hasResolution = false;
        /// <summary>
        /// Gets a value indicating whether the information about image resolution is stored
        /// in a BMP page.
        /// </summary>
        /// <value>
        /// <b>True</b> - the <see cref="Resolution"/> property returns resolution loaded from image file;<br />
        /// <b>false</b> - the <see cref="Resolution"/> property returns the default (screen) resolution.
        /// </value>
        /// <seealso cref="Resolution"/>
        public override bool HasResolution
        {
            get 
            {
                return _hasResolution;
            }
        }
    
        Vintasoft.Imaging.PixelFormat _imagePixelFormat = Vintasoft.Imaging.PixelFormat.Undefined;
        /// <summary>
        /// Gets the pixel format of this page.
        /// </summary>
        public Vintasoft.Imaging.PixelFormat PixelFormat
        {
            get
            {
                return _imagePixelFormat;
            }
        }
    
        #endregion
    
    
    
        #region Methods
    
        #region PUBLIC
    
        /// <summary>
        /// Gets the image associated with this image page.
        /// </summary>
        /// <param name="decodingSettings">Decoding settings used for decode the image of page.</param>
        /// <param name="progressDelegate">Progress delegate.
        /// Can be set to null (Nothing in Visual Basic).</param>
        /// <returns>The image associated with this BMP page if image was loaded successfully;
        /// otherwise, null.</returns>
        public override Vintasoft.Imaging.VintasoftImage GetImage(
            Vintasoft.Imaging.Codecs.Decoders.DecodingSettings decodingSettings,
            System.EventHandler<Vintasoft.Imaging.ProgressEventArgs> progressDelegate)
        {
            // create image
            Vintasoft.Imaging.VintasoftImage image = new Vintasoft.Imaging.VintasoftImage(Width, Height, _imagePixelFormat);
    
            // if resolution is empty
            if (_resolution.IsEmpty())
                image.Resolution = Vintasoft.Imaging.ImagingEnvironment.ScreenResolution;
            else
            {
                _hasResolution = true;
                image.Resolution = _resolution;
            }
    
            // open pixel manipulator
            Vintasoft.Imaging.PixelManipulator pixelManipulator = image.OpenPixelManipulator();
            System.Drawing.Rectangle lockPixelsRectangle = new System.Drawing.Rectangle(0, 0, Width, Height);
            // lock pixels
            pixelManipulator.LockPixelsForSerialAccess(lockPixelsRectangle, Vintasoft.Imaging.BitmapLockMode.Write,
                 _imagePixelFormat, new byte[_stride], _reverseReadWrite);
            try
            {
                // lock the original image source (image source from which BMP page must be read)
                lock (Source.Stream)
                {
                    // go to the start of image data in original image source
                    Source.Position = _offsetToImageData;
                    // get serial buffer of pixel manipulator
                    byte[] buffer = pixelManipulator.SerialBuffer;
                    int yStart = Height - 1;
    
                    int previousProgress = -1;
                    double progressStep = 100.0 / yStart;
                    double currentProgress = -progressStep;
    
                    // for each image row
                    for (int y = yStart; y >= 0; y--)
                    {
                        // if progress must be generated
                        if (progressDelegate != null)
                        {
                            // calculate current progress
                            currentProgress += progressStep;
                            // if previous and current progress are different
                            if (previousProgress != (int)System.Math.Round(currentProgress))
                            {
                                // get the progress integer value
                                previousProgress = (int)System.Math.Round(currentProgress);
                                // raise the progress event
                                progressDelegate(this, new Vintasoft.Imaging.ProgressEventArgs(previousProgress));
                            }
                        }
    
                        // read row data from image source
                        Source.ReadBytes(buffer);
                        // write row data to the pixel manipulator
                        pixelManipulator.WriteRowAndMoveToNext();
                    }
                }
            }
            finally
            {
                // unlock pixels
                pixelManipulator.UnlockPixels();
                // close pixel manipulator
                image.ClosePixelManipulator(true);
            }
    
            return image;
        }
    
        /// <summary>
        /// Saves the page to the image source.
        /// </summary>
        /// <param name="source">Image source.</param>
        /// <param name="progressController">Progress controller.</param>
        public override void Save(Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source,
            Vintasoft.Imaging.Utils.IProgressController progressController)
        {
            // raise the Saving event
            OnSaving(System.EventArgs.Empty);
    
            // if progress controller is specified
            if (progressController != null)
            {
                // specify that there is only one progress stage
                progressController.Start(1);
                // start the progress stage
                progressController.NextStage(this, false);
            }
    
            // lock the destination image source (image source where BMP page must be written)
            lock (source.Stream)
            {
                // write header to the destination image source
                WriteHeader(source);
    
                // lock the original image source (image source from which BMP page must be read)
                lock (Source.Stream)
                {
                    // go to the start of image data in original image source
                    Source.Position = _offsetToImageData;
                    // create buffer for row data
                    byte[] buffer = new byte[_stride];
    
                    // if progress controller is specified
                    if (progressController != null)
                        // specify the count of progress steps
                        progressController.StartSteps((int)System.Math.Ceiling((double)_imageSize / buffer.Length));
    
                    uint writeBytesCount = 0;
    
                    // while the count of written bytes less than image size
                    while (writeBytesCount != _imageSize)
                    {
                        // if progress controller is specified
                        if (progressController != null)
                        {
                            // raise progress and check if saving process must be canceled
                            if (!progressController.NextStep(this, true))
                                // cancel saving process
                                break;
                        }
    
                        // get count of bytes to read
                        int bytesToRead = (int)System.Math.Min(_imageSize - writeBytesCount, buffer.Length);
    
                        // read image row data from original image source
                        this.Source.ReadBytes(buffer, 0, bytesToRead);
                        // write image row data to the destination image source
                        source.WriteBytes(buffer, 0, bytesToRead);
    
                        // update the count of written bytes
                        writeBytesCount += (uint)bytesToRead;
                    }
    
                    // if progress controller is specified
                    if (progressController != null)
                        // finish a sequence of progress steps
                        progressController.FinishSteps(this);
                }
            }
    
            // if progress controller is specified
            if (progressController != null)
                // finish the progress stage
                progressController.Finish(this);
    
            // raise the Saved event
            OnSaved(new Vintasoft.Imaging.Codecs.ImageFiles.ImageFileBlockSourceInfoChangedEventArgs());
        }
    
        #endregion
    
    
        #region PROTECTED
    
        /// <summary>
        /// Parse the BMP page.
        /// </summary>
        protected override void Parse()
        {
            // lock the original image source (image source from which BMP page must be read)
            lock (Source.Stream)
            {
                // read info block length
                uint infoBlockLength = Source.ReadUInt32();
    
                // if info block is not standard
                if (infoBlockLength != BITMAPINFOHEADER_LENGTH)
                    throw new System.NotSupportedException("Unsupported bitmap info block.");
    
                // LONG biWidth
                _width = Source.ReadInt32();
    
                // LONG biHeight
                _height = Source.ReadInt32();
                _reverseReadWrite = _height > 0;
    
                // WORD biPlanes
                Source.Position += 2;
    
                // WORD biBitCount
                System.UInt16 bitCount = Source.ReadUInt16();
                _bitsPerPixel = bitCount;
    
                switch (bitCount)
                {
                    case 24:
                        _imagePixelFormat = Vintasoft.Imaging.PixelFormat.Bgr24;
                        break;
    
                    case 32:
                        _imagePixelFormat = Vintasoft.Imaging.PixelFormat.Bgr32;
                        break;
    
                    default:
                        throw new System.NotSupportedException("Unsupported pixel format.");
                }
    
                // calculate stride
                _stride = Vintasoft.Imaging.VintasoftBitmap.GetStride(_imagePixelFormat, Width);
    
                // DWORD biCompression;
                System.UInt32 compression = Source.ReadUInt32();
    
                // if image is compressed
                if (compression != 0)
                    throw new System.NotSupportedException("Compressed data is not supported.");
    
                // DWORD biSizeImage;
                _imageSize = Source.ReadUInt32();
    
                if (_imageSize == 0)
                    _imageSize = (uint)(_stride * Height);
    
                // LONG biXPelsPerMeter;
                float dpiX = Source.ReadInt32() / (100f * (1f / 2.54f));
    
                // LONG biYPelsPerMeter;
                float dpiY = Source.ReadInt32() / (100f * (1f / 2.54f));
    
                // set resolution
                _resolution = new Vintasoft.Imaging.Resolution(dpiX, dpiY);
                _hasResolution = true;
    
                // set page block
                SetLength(BITMAPINFOHEADER_LENGTH + _imageSize);
            }
        }
    
        #endregion
    
    
        #region INTERNAL
    
        /// <summary>
        /// Writes BMP page header.
        /// </summary>
        /// <param name="source">Image source where BMP page must be written.</param>
        internal void WriteHeader(Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source)
        {
            // lock the destination image source (image source where BMP page must be written)
            lock (source.Stream)
            {
                // DWORD biSize
                source.WriteUInt32(BITMAPINFOHEADER_LENGTH);
    
                // LONG biWidth
                source.WriteInt32(_width);
    
                // LONG biHeight
                source.WriteInt32(_height);
    
                // WORD biPlanes
                source.WriteUInt16(1);
    
                // WORD biBitCount
                source.WriteUInt16((System.UInt16)_bitsPerPixel);
    
                // DWORD biCompression
                source.WriteUInt32(0);
    
                // DWORD biSizeImage
                source.WriteUInt32(_imageSize);
    
                int dpiX = 0;
                int dpiY = 0;
                // if resolution is not empty
                if (!_resolution.IsEmpty())
                {
                    dpiX = (int)System.Math.Round(_resolution.Horizontal * (100.0f * (1.0f / 2.54f)));
                    dpiY = (int)System.Math.Round(_resolution.Vertical * (100.0f * (1.0f / 2.54f)));
                }
    
                // LONG biXPelsPerMeter
                source.WriteInt32(dpiX);
    
                // LONG biYPelsPerMeter
                source.WriteInt32(dpiY);
    
                // DWORD biClrUsed
                source.WriteUInt32(0);
    
                // DWORD biClrImportant
                source.WriteUInt32(0);
            }
        }
    
        #endregion
    
    
        #region PRIVATE
    
        /// <summary>
        /// Encodes an image data.
        /// </summary>
        /// <param name="source">Image source.</param>
        /// <param name="image">Image.</param>
        private void EncodeImageData(Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource source, 
            Vintasoft.Imaging.VintasoftImage image)
        {
            // open the pixel manipulator
            Vintasoft.Imaging.PixelManipulator pixelManipulator = image.OpenPixelManipulator();
    
            // lock pixels
            System.Drawing.Rectangle lockPixelsRectangle = new System.Drawing.Rectangle(0, 0, Width, Height);
            pixelManipulator.LockPixelsForSerialAccess(lockPixelsRectangle, Vintasoft.Imaging.BitmapLockMode.Write,
                _imagePixelFormat, new byte[_stride], _reverseReadWrite);
    
            try
            {
                // lock the original image source (image source from which BMP page must be read)
                lock (Source.Stream)
                {
                    // go to the start of image data in original image source
                    Source.Position = _offsetToImageData;
    
                    // get serial buffer of pixel manipulator
                    byte[] buffer = pixelManipulator.SerialBuffer;
    
                    // for each image row
                    int yStart = Height - 1;
                    for (int y = yStart; y >= 0; y--)
                    {
                        // read row data from pixel manipulator
                        pixelManipulator.ReadRowAndMoveToNext();
                        // write row data to the image source
                        Source.WriteBytes(buffer);
                    }
                }
            }
            finally
            {
                // unlock pixels
                pixelManipulator.UnlockPixels();
                // close the pixel manipulator
                image.ClosePixelManipulator(false);
            }
        }
    
        #endregion
    
        #endregion
    
    }
    
    ''' <summary>
    ''' Class that allows to get information about BMP page.
    ''' </summary>
    Public Class SimpleBmpPage
        Inherits Vintasoft.Imaging.Codecs.ImageFiles.ImagePage
    
        #Region "Fields"
    
        ''' <summary>
        ''' BMP page info header length.
        ''' </summary>
        Friend Const BITMAPINFOHEADER_LENGTH As UInteger = 40
    
        ''' <summary>
        ''' Image stride (row width in bytes).
        ''' </summary>
        Private _stride As Integer
    
        ''' <summary>
        ''' Indicates that image raw data is reversed.
        ''' </summary>
        Private _reverseReadWrite As Boolean
    
        ''' <summary>
        ''' Image raw data offset, in bytes.
        ''' </summary>
        Private _offsetToImageData As Long
    
        ''' <summary>
        ''' Image length, in bytes.
        ''' </summary>
        Private _imageSize As UInteger
    
        #End Region
    
    
    
        #Region "Constructors"
    
        ''' <summary>
        ''' Initializes a new instance of the <see cref="SimpleBmpPage"/> class.
        ''' </summary>
        ''' <param name="source">Source of the image page.</param>
        ''' <param name="offset">Offset of the image page in the source.</param>
        Public Sub New(source As Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource, offset As Long)
            MyBase.New(source, offset)
            _offsetToImageData = offset
            Parse()
        End Sub
    
        ''' <summary>
        ''' Initializes a new instance of the <see cref="SimpleBmpPage"/> class.
        ''' </summary>
        ''' <param name="source">Source of the image page.</param>
        ''' <param name="image">New image.</param>
        Public Sub New(source__1 As Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource, image As Vintasoft.Imaging.VintasoftImage)
            MyBase.New(source__1, 0)
            ' sets the image settings
            _offsetToImageData = 0
            _imagePixelFormat = image.PixelFormat
            _width = image.Width
            _height = image.Height
            _resolution = image.Resolution
            _hasResolution = True
            _bitsPerPixel = image.BitsPerPixel
    
            ' calculate stride of image
            _stride = Vintasoft.Imaging.VintasoftBitmap.GetStride(_imagePixelFormat, Width)
            ' image is reverse
            _reverseReadWrite = True
    
            ' encode image data
            EncodeImageData(Source, image)
    
            ' set the image length
            _imageSize = CUInt(Source.Length)
            ' set bmp page length
            SetLength(BITMAPINFOHEADER_LENGTH + _imageSize)
        End Sub
    
        #End Region
    
    
    
        #Region "Properties"
    
        Private _width As Integer
        ''' <summary>
        ''' Gets the width, in pixels, of the image page.
        ''' </summary>
        Public Overrides ReadOnly Property Width() As Integer
            Get
                Return _width
            End Get
        End Property
    
        Private _height As Integer
        ''' <summary>
        ''' Gets the height, in pixels, of the image page.
        ''' </summary>
        Public Overrides ReadOnly Property Height() As Integer
            Get
                Return System.Math.Abs(_height)
            End Get
        End Property
    
        Private _bitsPerPixel As Integer
        ''' <summary>
        ''' Gets the bit depth of the image page.
        ''' </summary>
        Public Overrides ReadOnly Property BitsPerPixel() As Integer
            Get
                Return _bitsPerPixel
            End Get
        End Property
    
        Private _palette As Vintasoft.Imaging.Palette = Nothing
        ''' <summary>
        ''' Gets the palette of the image page.
        ''' </summary>
        Public Overrides ReadOnly Property Palette() As Vintasoft.Imaging.Palette
            Get
                Return _palette
            End Get
        End Property
    
        Private _resolution As Vintasoft.Imaging.Resolution = Vintasoft.Imaging.Resolution.Empty
        ''' <summary>
        ''' Gets or sets the resolution, in pixels per inch, of the image page.
        ''' </summary>
        ''' <value>
        ''' The resolution loaded from an image metadata if <see cref="HasResolution"/> returns <b>true</b>;
        ''' otherwise, the default (screen) resolution.
        ''' </value>
        ''' <seealso cref="HasResolution"/>
        Public Overrides Property Resolution() As Vintasoft.Imaging.Resolution
            Get
                If _resolution = Vintasoft.Imaging.Resolution.Empty Then
                    Return Vintasoft.Imaging.ImagingEnvironment.ScreenResolution
                End If
                Return _resolution
            End Get
            Set
                Throw New System.NotImplementedException()
            End Set
        End Property
    
        Private _hasResolution As Boolean = False
        ''' <summary>
        ''' Gets a value indicating whether the information about image resolution is stored
        ''' in a BMP page.
        ''' </summary>
        ''' <value>
        ''' <b>True</b> - the <see cref="Resolution"/> property returns resolution loaded from image file;<br />
        ''' <b>false</b> - the <see cref="Resolution"/> property returns the default (screen) resolution.
        ''' </value>
        ''' <seealso cref="Resolution"/>
        Public Overrides ReadOnly Property HasResolution() As Boolean
            Get
                Return _hasResolution
            End Get
        End Property
    
        Private _imagePixelFormat As Vintasoft.Imaging.PixelFormat = Vintasoft.Imaging.PixelFormat.Undefined
        ''' <summary>
        ''' Gets the pixel format of this page.
        ''' </summary>
        Public ReadOnly Property PixelFormat() As Vintasoft.Imaging.PixelFormat
            Get
                Return _imagePixelFormat
            End Get
        End Property
    
        #End Region
    
    
    
        #Region "Methods"
    
        #Region "PUBLIC"
    
        ''' <summary>
        ''' Gets the image associated with this image page.
        ''' </summary>
        ''' <param name="decodingSettings">Decoding settings used for decode the image of page.</param>
        ''' <param name="progressDelegate">Progress delegate.
        ''' Can be set to null (Nothing in Visual Basic).</param>
        ''' <returns>The image associated with this BMP page if image was loaded successfully;
        ''' otherwise, null.</returns>
        Public Overrides Function GetImage(decodingSettings As Vintasoft.Imaging.Codecs.Decoders.DecodingSettings, progressDelegate As System.EventHandler(Of Vintasoft.Imaging.ProgressEventArgs)) As Vintasoft.Imaging.VintasoftImage
            ' create image
            Dim image As New Vintasoft.Imaging.VintasoftImage(Width, Height, _imagePixelFormat)
    
            ' if resolution is empty
            If _resolution.IsEmpty() Then
                image.Resolution = Vintasoft.Imaging.ImagingEnvironment.ScreenResolution
            Else
                _hasResolution = True
                image.Resolution = _resolution
            End If
    
            ' open pixel manipulator
            Dim pixelManipulator As Vintasoft.Imaging.PixelManipulator = image.OpenPixelManipulator()
            Dim lockPixelsRectangle As New System.Drawing.Rectangle(0, 0, Width, Height)
            ' lock pixels
            pixelManipulator.LockPixelsForSerialAccess(lockPixelsRectangle, Vintasoft.Imaging.BitmapLockMode.Write, _imagePixelFormat, New Byte(_stride - 1) {}, _reverseReadWrite)
            Try
                ' lock the original image source (image source from which BMP page must be read)
                SyncLock Source.Stream
                    ' go to the start of image data in original image source
                    Source.Position = _offsetToImageData
                    ' get serial buffer of pixel manipulator
                    Dim buffer As Byte() = pixelManipulator.SerialBuffer
                    Dim yStart As Integer = Height - 1
    
                    Dim previousProgress As Integer = -1
                    Dim progressStep As Double = 100.0 / yStart
                    Dim currentProgress As Double = -progressStep
    
                    ' for each image row
                    For y As Integer = yStart To 0 Step -1
                        ' if progress must be generated
                        If progressDelegate IsNot Nothing Then
                            ' calculate current progress
                            currentProgress += progressStep
                            ' if previous and current progress are different
                            If previousProgress <> CInt(Math.Truncate(System.Math.Round(currentProgress))) Then
                                ' get the progress integer value
                                previousProgress = CInt(Math.Truncate(System.Math.Round(currentProgress)))
                                ' raise the progress event
                                progressDelegate(Me, New Vintasoft.Imaging.ProgressEventArgs(previousProgress))
                            End If
                        End If
    
                        ' read row data from image source
                        Source.ReadBytes(buffer)
                        ' write row data to the pixel manipulator
                        pixelManipulator.WriteRowAndMoveToNext()
                    Next
                End SyncLock
            Finally
                ' unlock pixels
                pixelManipulator.UnlockPixels()
                ' close pixel manipulator
                image.ClosePixelManipulator(True)
            End Try
    
            Return image
        End Function
    
        ''' <summary>
        ''' Saves the page to the image source.
        ''' </summary>
        ''' <param name="source">Image source.</param>
        ''' <param name="progressController">Progress controller.</param>
        Public Overrides Sub Save(source__1 As Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource, progressController As Vintasoft.Imaging.Utils.IProgressController)
            ' raise the Saving event
            OnSaving(System.EventArgs.Empty)
    
            ' if progress controller is specified
            If progressController IsNot Nothing Then
                ' specify that there is only one progress stage
                progressController.Start(1)
                ' start the progress stage
                progressController.NextStage(Me, False)
            End If
    
            ' lock the destination image source (image source where BMP page must be written)
            SyncLock source__1.Stream
                ' write header to the destination image source
                WriteHeader(source__1)
    
                ' lock the original image source (image source from which BMP page must be read)
                SyncLock Source.Stream
                    ' go to the start of image data in original image source
                    Source.Position = _offsetToImageData
                    ' create buffer for row data
                    Dim buffer As Byte() = New Byte(_stride - 1) {}
    
                    ' if progress controller is specified
                    If progressController IsNot Nothing Then
                        ' specify the count of progress steps
                        progressController.StartSteps(CInt(Math.Truncate(System.Math.Ceiling(CDbl(_imageSize) / buffer.Length))))
                    End If
    
                    Dim writeBytesCount As UInteger = 0
    
                    ' while the count of written bytes less than image size
                    While writeBytesCount <> _imageSize
                        ' if progress controller is specified
                        If progressController IsNot Nothing Then
                            ' raise progress and check if saving process must be canceled
                            If Not progressController.NextStep(Me, True) Then
                                ' cancel saving process
                                Exit While
                            End If
                        End If
    
                        ' get count of bytes to read
                        Dim bytesToRead As Integer = CInt(System.Math.Min(_imageSize - writeBytesCount, buffer.Length))
    
                        ' read image row data from original image source
                        Me.Source.ReadBytes(buffer, 0, bytesToRead)
                        ' write image row data to the destination image source
                        source__1.WriteBytes(buffer, 0, bytesToRead)
    
                        ' update the count of written bytes
                        writeBytesCount += CUInt(bytesToRead)
                    End While
    
                    ' if progress controller is specified
                    If progressController IsNot Nothing Then
                        ' finish a sequence of progress steps
                        progressController.FinishSteps(Me)
                    End If
                End SyncLock
            End SyncLock
    
            ' if progress controller is specified
            If progressController IsNot Nothing Then
                ' finish the progress stage
                progressController.Finish(Me)
            End If
    
            ' raise the Saved event
            OnSaved(New Vintasoft.Imaging.Codecs.ImageFiles.ImageFileBlockSourceInfoChangedEventArgs())
        End Sub
    
        #End Region
    
    
        #Region "PROTECTED"
    
        ''' <summary>
        ''' Parse the BMP page.
        ''' </summary>
        Protected Overrides Sub Parse()
            ' lock the original image source (image source from which BMP page must be read)
            SyncLock Source.Stream
                ' read info block length
                Dim infoBlockLength As UInteger = Source.ReadUInt32()
    
                ' if info block is not standard
                If infoBlockLength <> BITMAPINFOHEADER_LENGTH Then
                    Throw New System.NotSupportedException("Unsupported bitmap info block.")
                End If
    
                ' LONG biWidth
                _width = Source.ReadInt32()
    
                ' LONG biHeight
                _height = Source.ReadInt32()
                _reverseReadWrite = _height > 0
    
                ' WORD biPlanes
                Source.Position += 2
    
                ' WORD biBitCount
                Dim bitCount As System.UInt16 = Source.ReadUInt16()
                _bitsPerPixel = bitCount
    
                Select Case bitCount
                    Case 24
                        _imagePixelFormat = Vintasoft.Imaging.PixelFormat.Bgr24
                        Exit Select
    
                    Case 32
                        _imagePixelFormat = Vintasoft.Imaging.PixelFormat.Bgr32
                        Exit Select
                    Case Else
    
                        Throw New System.NotSupportedException("Unsupported pixel format.")
                End Select
    
                ' calculate stride
                _stride = Vintasoft.Imaging.VintasoftBitmap.GetStride(_imagePixelFormat, Width)
    
                ' DWORD biCompression;
                Dim compression As System.UInt32 = Source.ReadUInt32()
    
                ' if image is compressed
                If compression <> 0 Then
                    Throw New System.NotSupportedException("Compressed data is not supported.")
                End If
    
                ' DWORD biSizeImage;
                _imageSize = Source.ReadUInt32()
    
                If _imageSize = 0 Then
                    _imageSize = CUInt(_stride * Height)
                End If
    
                ' LONG biXPelsPerMeter;
                Dim dpiX As Single = Source.ReadInt32() / (100F * (1F / 2.54F))
    
                ' LONG biYPelsPerMeter;
                Dim dpiY As Single = Source.ReadInt32() / (100F * (1F / 2.54F))
    
                ' set resolution
                _resolution = New Vintasoft.Imaging.Resolution(dpiX, dpiY)
                _hasResolution = True
    
                ' set page block
                SetLength(BITMAPINFOHEADER_LENGTH + _imageSize)
            End SyncLock
        End Sub
    
        #End Region
    
    
        #Region "INTERNAL"
    
        ''' <summary>
        ''' Writes BMP page header.
        ''' </summary>
        ''' <param name="source">Image source where BMP page must be written.</param>
        Friend Sub WriteHeader(source As Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource)
            ' lock the destination image source (image source where BMP page must be written)
            SyncLock source.Stream
                ' DWORD biSize
                source.WriteUInt32(BITMAPINFOHEADER_LENGTH)
    
                ' LONG biWidth
                source.WriteInt32(_width)
    
                ' LONG biHeight
                source.WriteInt32(_height)
    
                ' WORD biPlanes
                source.WriteUInt16(1)
    
                ' WORD biBitCount
                source.WriteUInt16(CUShort(_bitsPerPixel))
    
                ' DWORD biCompression
                source.WriteUInt32(0)
    
                ' DWORD biSizeImage
                source.WriteUInt32(_imageSize)
    
                Dim dpiX As Integer = 0
                Dim dpiY As Integer = 0
                ' if resolution is not empty
                If Not _resolution.IsEmpty() Then
                    dpiX = CInt(Math.Truncate(System.Math.Round(_resolution.Horizontal * (100F * (1F / 2.54F)))))
                    dpiY = CInt(Math.Truncate(System.Math.Round(_resolution.Vertical * (100F * (1F / 2.54F)))))
                End If
    
                ' LONG biXPelsPerMeter
                source.WriteInt32(dpiX)
    
                ' LONG biYPelsPerMeter
                source.WriteInt32(dpiY)
    
                ' DWORD biClrUsed
                source.WriteUInt32(0)
    
                ' DWORD biClrImportant
                source.WriteUInt32(0)
            End SyncLock
        End Sub
    
        #End Region
    
    
        #Region "PRIVATE"
    
        ''' <summary>
        ''' Encodes an image data.
        ''' </summary>
        ''' <param name="source">Image source.</param>
        ''' <param name="image">Image.</param>
        Private Sub EncodeImageData(source__1 As Vintasoft.Imaging.Codecs.ImageFiles.ImageFileSource, image As Vintasoft.Imaging.VintasoftImage)
            ' open the pixel manipulator
            Dim pixelManipulator As Vintasoft.Imaging.PixelManipulator = image.OpenPixelManipulator()
    
            ' lock pixels
            Dim lockPixelsRectangle As New System.Drawing.Rectangle(0, 0, Width, Height)
            pixelManipulator.LockPixelsForSerialAccess(lockPixelsRectangle, Vintasoft.Imaging.BitmapLockMode.Write, _imagePixelFormat, New Byte(_stride - 1) {}, _reverseReadWrite)
    
            Try
                ' lock the original image source (image source from which BMP page must be read)
                SyncLock Source.Stream
                    ' go to the start of image data in original image source
                    Source.Position = _offsetToImageData
    
                    ' get serial buffer of pixel manipulator
                    Dim buffer As Byte() = pixelManipulator.SerialBuffer
    
                    ' for each image row
                    Dim yStart As Integer = Height - 1
                    For y As Integer = yStart To 0 Step -1
                        ' read row data from pixel manipulator
                        pixelManipulator.ReadRowAndMoveToNext()
                        ' write row data to the image source
                        Source.WriteBytes(buffer)
                    Next
                End SyncLock
            Finally
                ' unlock pixels
                pixelManipulator.UnlockPixels()
                ' close the pixel manipulator
                image.ClosePixelManipulator(False)
            End Try
        End Sub
    
        #End Region
    
        #End Region
    
    End Class