private static void applyDwtDctWatermarkOnColorSpace(double[,] colorSpaceTarget, double[,] greyScaleWatermark)
        {
            var a         = colorSpaceTarget[0, 0];
            var flattened = greyScaleWatermark.Cast <double>().ToArray();

            DWTTransform.ForwardTransform(colorSpaceTarget, 2);
            var subBandTarget        = WatermarkUtils.Ll1(colorSpaceTarget);
            var midband              = GetMidBand(DCT_BLOCK_SIZE);
            var embeddingBlockLength = subBandTarget.GetLength(0);

            var midBandOneElementsCount = midband.Cast <double>().Count(el => (int)el == 1);

            var(pnSequenceZero, pnSequenceOne) = GenerateUncorelatedPnSequences(midBandOneElementsCount);

            var x = 0;
            var y = 0;

            for (int i = 0; i < flattened.Length; i++)
            {
                var block = subBandTarget.Submatrix(y, y + DCT_BLOCK_SIZE - 1,
                                                    x, x + DCT_BLOCK_SIZE - 1);

                DCTTransform.DCT(block);

                var ll = 0;

                for (int j = 0; j < midband.GetLength(0); j++)
                {
                    for (int k = 0; k < midband.GetLength(1); k++)
                    {
                        if (midband[j, k] == 1)
                        {
                            var elementToAdd = flattened[i] == 0 ? pnSequenceOne[ll] : pnSequenceZero[ll];
                            block[j, k] = block[j, k] + elementToAdd * WATERMARK_FACTOR;
                            ll++;
                        }
                    }
                }

                DCTTransform.IDCT(block);

                subBandTarget.ApplyDataBlock(block, y, x);

                x += DCT_BLOCK_SIZE;

                if (x + DCT_BLOCK_SIZE >= embeddingBlockLength)
                {
                    x  = 1;
                    y += DCT_BLOCK_SIZE;

                    if (y >= embeddingBlockLength)
                    {
                        break;
                    }
                }
            }

            ;

            WatermarkUtils.ApplyLl1SubBand(colorSpaceTarget, subBandTarget);
            DWTTransform.InverseWaveletTransform(colorSpaceTarget, 2);
        }
        private static Bitmap ExtractDwtDctWatermark(double[,] iWatermarked, double[,] greyScaleWatermark)
        {
            var flattened = greyScaleWatermark.Cast <double>().ToArray();

            DWTTransform.ForwardTransform(iWatermarked, 2);

            var subBandTarget           = WatermarkUtils.Ll1(iWatermarked);
            var midband                 = GetMidBand(DCT_BLOCK_SIZE);
            var embeddingBlockLength    = subBandTarget.GetLength(0);
            var midBandOneElementsCount = midband.Cast <double>().Count(el => (int)el == 1);

            var(pnSequenceZero, pnSequenceOne) = GenerateUncorelatedPnSequences(midBandOneElementsCount);
            var sequence        = new double[pnSequenceOne.Count];
            var correlationZero = new double[flattened.Length];
            var correlationOne  = new double[flattened.Length];

            var x = 0;
            var y = 0;

            for (var i = 0; i < flattened.Length; i++)
            {
                var block = subBandTarget.Submatrix(y, y + DCT_BLOCK_SIZE - 1,
                                                    x, x + DCT_BLOCK_SIZE - 1);
                DCTTransform.DCT(block);

                var ll = 0;

                for (var j = 0; j < midband.GetLength(0); j++)
                {
                    for (var k = 0; k < midband.GetLength(1); k++)
                    {
                        if (midband[j, k] == 1)
                        {
                            sequence[ll] = block[j, k];
                            ll++;
                        }
                    }
                }

                correlationZero[i] = Correlation.Pearson(pnSequenceZero, sequence);
                correlationOne[i]  = Correlation.Pearson(pnSequenceOne, sequence);

                x += DCT_BLOCK_SIZE;

                if (x + DCT_BLOCK_SIZE >= embeddingBlockLength)
                {
                    x  = 1;
                    y += DCT_BLOCK_SIZE;

                    if (y >= embeddingBlockLength)
                    {
                        break;
                    }
                }
            }

            var reconstructedImage = new int [flattened.Length];

            for (var i = 0; i < flattened.Length; i++)
            {
                if (correlationZero[i] > correlationOne[i])
                {
                    reconstructedImage[i] = 255;
                }
                else
                {
                    reconstructedImage[i] = 0;
                }
            }

            var imgLength = greyScaleWatermark.GetLength(0);
            var img       = new int[greyScaleWatermark.GetLength(0), greyScaleWatermark.GetLength(1)];

            for (var i = 0; i < reconstructedImage.Length; i++)
            {
                img[i / imgLength, i % imgLength] = reconstructedImage[i];
            }

            return(BitmapUtils.CreateGeyscaleImage(img));
        }