コード例 #1
0
        /// <summary>
        /// Uncompress image using 10 iterations.
        /// </summary>
        /// <param name="compressionResult">Compressed image result.</param>
        /// <param name="decodingImage">Image used for decoding.</param>
        /// <returns>Custom Image.</returns>
        public CustomImage CompleteUncompress(FractalCompressionResult compressionResult, CustomImage decodingImage)
        {
            using (new CustomTimer("Complete decompression"))
            {
                for (int i = 0; i < 10; i++)
                {
                    decodingImage = Uncompress(compressionResult, decodingImage);
                }
            }

            //if (_options.SmoothImage)
            //    return new CustomImage(SmoothImage(decodingImage.ImageData, _options.RSquareSize));
            //else
            return(decodingImage);
        }
        public CustomImage Uncompress(FractalCompressionResult compressionResult, CustomImage decodingImage)
        {
            const int dimensions = 3;
            int       rXCount    = compressionResult.RCountX;
            int       rYCount    = compressionResult.Transformations.GetLength(0) / compressionResult.RCountX;
            int       imgSizeX   = rXCount * _options.RSquareSize;
            int       imgSizeY   = rYCount * _options.RSquareSize;

            //if (decodingImage.Width != imgSizeX || decodingImage.Height != imgSizeY)
            //    throw new ArgumentException("Decoding image must be the same size that the compressed image!");

            Pixel[,] pixels = new Pixel[imgSizeX, imgSizeY];
            double drRatio               = (double)_options.RSquareSize / (double)_options.DSquareSize;
            int    drInverseRatio        = _options.DSquareSize / _options.RSquareSize;
            int    dSizeXAdapted         = decodingImage.Width / (rXCount / drInverseRatio);
            int    dSizeYAdapted         = decodingImage.Height / (rYCount / drInverseRatio);
            double drRatioAdapted        = (double)_options.RSquareSize / dSizeXAdapted;
            int    drInverseRatioAdapted = dSizeXAdapted / _options.RSquareSize;
            int    maxDxPos              = imgSizeX - _options.DSquareSize + 1;
            int    maxDyPos              = imgSizeY - _options.DSquareSize + 1;
            int    dSize = _options.DSquareSize;
            int    rSize = _options.RSquareSize;

            double[, ][][,] tempDi = new double[maxDxPos, maxDyPos][][, ];
            double[,,] imgData     = new double[imgSizeX, imgSizeY, dimensions];
            var    rawImgData             = decodingImage.ImageData;
            double pixelAverageSquareSize = (double)drInverseRatioAdapted * (double)drInverseRatioAdapted;
            var    translateMatrixes      = GetTranslateMatrixes(_options.RSquareSize);

            //Fill imgData Y, I and Q
            Parallel.For(0, imgSizeX, dx =>
            {
                for (int dy = 0; dy < imgSizeY; dy++)
                {
                    imgData[dx, dy, 0] = rawImgData[dx, dy].YNormalized;
                    imgData[dx, dy, 1] = rawImgData[dx, dy].IDownSampledAndNormalized;
                    imgData[dx, dy, 2] = rawImgData[dx, dy].QDownSampledAndNormalized;
                }
            });

            //Subsample image to fit image to get Dis
            Parallel.For(0, maxDxPos, dx =>
            {
                int x, y, j, k, indexX = 0, indexY = 0;
                double[,] tempPixelY1  = null;
                double[,] tempPixelI1  = null;
                double[,] tempPixelQ1  = null;
                double tempSumY        = 0d, tempSumI = 0d, tempSumQ = 0d,
                tempAveragePixelY      = 0d, tempAveragePixelI = 0d, tempAveragePixelQ = 0d;

                for (int dy = 0; dy < maxDyPos; dy++)
                {
                    tempDi[dx, dy] = new double[dimensions][, ];

                    for (x = 0; x < dSize; x += drInverseRatioAdapted) //Increment of inverse ratio to get only parts of Di
                    {
                        for (y = 0; y < dSize; y += drInverseRatioAdapted)
                        {
                            //Reset temp variables
                            tempSumY    = 0;
                            tempSumI    = 0;
                            tempSumQ    = 0;
                            tempPixelY1 = new double[rSize, rSize];
                            tempPixelI1 = new double[rSize, rSize];
                            tempPixelQ1 = new double[rSize, rSize];

                            //Average pixels
                            for (j = 0; j < drInverseRatioAdapted; j++)
                            {
                                for (k = 0; k < drInverseRatioAdapted; k++)
                                {
                                    tempSumY += imgData[dx + x + j, dy + y + k, 0];
                                    tempSumI += imgData[dx + x + j, dy + y + k, 1];
                                    tempSumQ += imgData[dx + x + j, dy + y + k, 2];
                                }
                            }

                            //Calculating average Pixel Components
                            tempAveragePixelY = tempSumY > 0 ? tempSumY / pixelAverageSquareSize : 0d;
                            tempAveragePixelI = tempSumI > 0 ? tempSumI / pixelAverageSquareSize : 0d;
                            tempAveragePixelQ = tempSumQ > 0 ? tempSumQ / pixelAverageSquareSize : 0d;

                            indexX = (int)(y * drRatio);
                            indexY = (int)(x * drRatio);

                            ////Store pixel components for transformed Di (Fi)
                            tempPixelY1[indexX, indexY] = tempAveragePixelY;
                            tempPixelI1[indexX, indexY] = tempAveragePixelI;
                            tempPixelQ1[indexX, indexY] = tempAveragePixelQ;

                            ////Store pixels of Di
                            tempDi[dx, dy][0] = tempPixelY1;
                            tempDi[dx, dy][1] = tempPixelI1;
                            tempDi[dx, dy][2] = tempPixelQ1;
                        }
                    }
                }
            });

            //Uncompress image
            Parallel.For(0, rXCount, rx =>
            {
                int dimIndex, indexX, indexY, newX, newY;
                double[,] tempTransform;
                double[] tempTranslate;
                byte[,,] tempComponents = new byte[rSize, rSize, dimensions];
                FractalCompressionResult.FractalTransformation transformation;

                for (int ry = 0; ry < rYCount; ry++)
                {
                    //Get transformed Di (Ri)
                    for (indexX = 0; indexX < rSize; indexX++)
                    {
                        for (indexY = 0; indexY < rSize; indexY++)
                        {
                            for (dimIndex = 0; dimIndex < dimensions; dimIndex++)
                            {
                                transformation = compressionResult.Transformations[ry * rXCount + rx, dimIndex];
                                tempTransform  = _transformMatrixes[transformation.TransformationType];
                                tempTranslate  = translateMatrixes[transformation.TransformationType];

                                newX = (byte)(tempTransform[0, 0] * indexX + tempTransform[0, 1] * indexY + tempTranslate[0]);
                                newY = (byte)(tempTransform[1, 0] * indexX + tempTransform[1, 1] * indexY + tempTranslate[1]);

                                tempComponents[newX, newY, dimIndex] = (byte)(tempDi[transformation.DiX, transformation.DiY][dimIndex][indexX, indexY] * transformation.ContrastTransformation + transformation.BrightnessTransformation);
                            }
                        }
                    }

                    //Populate pixels from Ri calculated
                    for (indexX = 0; indexX < rSize; indexX++)
                    {
                        for (indexY = 0; indexY < rSize; indexY++)
                        {
                            pixels[rx * rSize + indexX, ry * rSize + indexY] = Pixel.FromYIQDownSampled(tempComponents[indexX, indexY, 0], tempComponents[indexX, indexY, 1], tempComponents[indexX, indexY, 2]);
                        }
                    }
                }
            });

            return(new CustomImage(pixels));
        }
コード例 #3
0
        /// <summary>
        /// Uncompress image compressed using fractal compression (single iteration of decompression).
        /// </summary>
        /// <param name="compressionResult">Compressed image result.</param>
        /// <param name="decodingImage">Image used for decoding.</param>
        /// <returns>Uncompressed image.</returns>
        public CustomImage Uncompress(FractalCompressionResult compressionResult, CustomImage decodingImage)
        {
            int rXCount  = compressionResult.RCountX;
            int rYCount  = compressionResult.Transformations.GetLength(0) / compressionResult.RCountX;
            int imgSizeX = rXCount * _options.RSquareSize;
            int imgSizeY = rYCount * _options.RSquareSize;

            Pixel[,] pixels = new Pixel[imgSizeX, imgSizeY];
            int rSize = _options.RSquareSize;

            const int dimensions = 3;

            byte   dSquareSize            = Convert.ToByte(_options.RSquareSize * _options.DSquareRatio);
            double drRatio                = (double)_options.RSquareSize / (double)dSquareSize;
            int    drInverseRatio         = _options.DSquareRatio;
            int    maxDxPos               = imgSizeX - dSquareSize + 1;
            int    maxDyPos               = imgSizeY - dSquareSize + 1;
            int    dSize                  = dSquareSize;
            var    imgData                = decodingImage.ImageData;
            int    pixelAverageSquareSize = drInverseRatio * drInverseRatio;
            var    translateMatrixes      = GetTranslateMatrixes(Convert.ToSByte(dSize));

            Parallel.For(0, rXCount, rx =>
            {
                int dimIndex, indexX, indexY, newX, newY, i, j, y;
                sbyte[,] tempTransform;
                sbyte[] tempTranslate;
                double[,,] tempComponents = new double[dSize, dSize, dimensions];
                double s, o;
                FractalCompressionResult.FractalTransformation transformation;
                double componentSumY;
                double componentSumI;
                double componentSumQ;

                for (int ry = 0; ry < rYCount; ry++)
                {
                    //Get transformed Di (Ri)
                    for (indexX = 0; indexX < dSize; indexX++)
                    {
                        for (indexY = 0; indexY < dSize; indexY++)
                        {
                            for (dimIndex = 0; dimIndex < dimensions; dimIndex++)
                            {
                                transformation = compressionResult.Transformations[ry * rXCount + rx, dimIndex];
                                tempTransform  = _transformMatrixes[transformation.TransformationType];
                                tempTranslate  = translateMatrixes[transformation.TransformationType];

                                newX = Convert.ToInt32(tempTransform[0, 0] * indexX + tempTransform[0, 1] * indexY + tempTranslate[0]);
                                newY = Convert.ToInt32(tempTransform[1, 0] * indexX + tempTransform[1, 1] * indexY + tempTranslate[1]);
                                s    = transformation.ContrastTransformation / (double)(S_BITS_VALUE) * (2d * S_MAX) - S_MAX;

                                if (dimIndex == 0)
                                {
                                    o = (transformation.BrightnessTransformation / (double)(O_BITS_VALUE - 1) * ((1d + Math.Abs(s)) * Y_LEVELS));

                                    if (s > 0d)
                                    {
                                        o -= s * Y_LEVELS;
                                    }

                                    tempComponents[newX, newY, dimIndex] = imgData[transformation.DiX + indexX, transformation.DiY + indexY].Y * s + o;
                                }
                                else if (dimIndex == 1)
                                {
                                    o = (transformation.BrightnessTransformation / (double)(O_BITS_VALUE - 1) * ((1d + Math.Abs(s)) * I_LEVELS));

                                    if (s > 0d)
                                    {
                                        o -= s * I_LEVELS;
                                    }

                                    tempComponents[newX, newY, dimIndex] = imgData[transformation.DiX + indexX, transformation.DiY + indexY].I * s + o;
                                }
                                else
                                {
                                    o = (transformation.BrightnessTransformation / (double)(O_BITS_VALUE - 1) * ((1d + Math.Abs(s)) * Q_LEVELS));

                                    if (s > 0d)
                                    {
                                        o -= s * Q_LEVELS;
                                    }

                                    tempComponents[newX, newY, dimIndex] = imgData[transformation.DiX + indexX, transformation.DiY + indexY].Q * s + o;
                                }
                            }
                        }
                    }

                    //Populate pixels from Ri calculated
                    for (indexX = 0; indexX < dSize; indexX += drInverseRatio)
                    {
                        for (indexY = 0; indexY < dSize; indexY += drInverseRatio)
                        {
                            componentSumY = 0;
                            componentSumI = 0;
                            componentSumQ = 0;

                            for (i = 0; i < drInverseRatio; i++)
                            {
                                for (j = 0; j < drInverseRatio; j++)
                                {
                                    componentSumY += tempComponents[indexX + i, indexY + j, 0];
                                    componentSumI += tempComponents[indexX + i, indexY + j, 1];
                                    componentSumQ += tempComponents[indexX + i, indexY + j, 2];
                                }
                            }

                            pixels[rx * rSize + indexX / drInverseRatio, ry * rSize + indexY / drInverseRatio] = Pixel.FromYIQ(
                                Convert.ToByte(Math.Max(Math.Min(componentSumY / (drInverseRatio * drInverseRatio), 255), 0)),
                                Convert.ToInt16(Math.Max(Math.Min(componentSumI / (drInverseRatio * drInverseRatio), 151), -151)),
                                Convert.ToInt16(Math.Max(Math.Min(componentSumQ / (drInverseRatio * drInverseRatio), 133), -133)));
                        }
                    }
                }
            });

            if (_options.SmoothImage)
            {
                pixels = SmoothImage(pixels, rSize);
            }

            return(new CustomImage(pixels));
        }