private void HandleFirstRow(IImagePredictor imagePredictor)
        {
            const byte a = 0;
            const byte c = 0;

            for (int column = 1; column < imageSize; column++)
            {
                var b = ImageCodes[0, column - 1];
                var predictedValue = imagePredictor.PredictValue(a, b, c);
                ImageCodes[0, column] = (byte)(predictedValue + ErrorMatrix[0, column]);
            }
        }
        private void HandleFirstColumn(IImagePredictor imagePredictor)
        {
            const byte b = 0;
            const byte c = 0;

            for (int row = 1; row < imageSize; row++)
            {
                var a = ImageCodes[row - 1, 0];
                var predictedValue = imagePredictor.PredictValue(a, b, c);
                ImageCodes[row, 0] = (byte)(predictedValue + ErrorMatrix[row, 0]);
            }
        }
        private void HandleFirstRow(IImagePredictor imagePredictor)
        {
            const byte a = 0;
            const byte c = 0;

            for (int column = 1; column < OriginalImage.Height; column++)
            {
                var b          = ImageCodes[0, column - 1];
                var prediction = imagePredictor.PredictValue(a, b, c);

                HandlePrediction(0, column, prediction);
            }
        }
        private void HandleFirstColumn(IImagePredictor imagePredictor)
        {
            const byte b = 0;
            const byte c = 0;

            for (int row = 1; row < OriginalImage.Width; row++)
            {
                var a          = ImageCodes[row - 1, 0];
                var prediction = imagePredictor.PredictValue(a, b, c);

                HandlePrediction(row, 0, prediction);
            }
        }
        public void EncodeImage(IFileReader fileReader, IFileWriter fileWriter, IImagePredictor imagePredictor)
        {
            if (fileReader == null)
            {
                throw new ArgumentNullException(nameof(fileReader));
            }

            if (fileWriter == null)
            {
                throw new ArgumentNullException(nameof(fileWriter));
            }

            if (imagePredictor == null)
            {
                throw new ArgumentNullException(nameof(imagePredictor));
            }

            ValidateImageFromFileReader(fileReader);
            GetImageFromFileReader(fileReader);

            ImageCodes       = new byte[OriginalImage.Width, OriginalImage.Height];
            PredictionMatrix = new byte[OriginalImage.Width, OriginalImage.Height];
            ErrorMatrix      = new int[OriginalImage.Width, OriginalImage.Height];

            UpdateImageCodes();

            HandleFirstPixel();
            HandleFirstColumn(imagePredictor);
            HandleFirstRow(imagePredictor);

            for (int row = 1; row < 256; row++)
            {
                for (int column = 1; column < 256; column++)
                {
                    var a = ImageCodes[row - 1, column];
                    var b = ImageCodes[row, column - 1];
                    var c = ImageCodes[row - 1, column - 1];

                    var prediction = imagePredictor.PredictValue(a, b, c);

                    HandlePrediction(row, column, prediction);
                }
            }

            CopyBitmapHeader(fileReader, fileWriter);
            WriteUsedImagePredictor(fileWriter, imagePredictor);
            errorMatrixWriter.WriteErrorMatrix(ErrorMatrix, fileWriter);

            fileWriter.Flush();
        }