Example #1
0
 public static ZsImage ScaleTo(this ZsImage image, int width, int height)
 {
     while (image.Width < width || image.Height < height)
     {
         image = image.ScaleUp2x();
     }
     return(image);
 }
Example #2
0
 public static ZsImage PyramidDownLab(this ZsImage labImage, bool blur)
 {
     return(labImage
            .FromLabToRgb()
            .FromRgbToArgb(Area2D.Create(0, 0, labImage.Width, labImage.Height))
            .PyramidDownArgb(blur)
            .FromArgbToRgb(new[] { 1.0, 1.0, 1.0 })
            .FromRgbToLab());
 }
Example #3
0
        public ZsImage Clone()
        {
            var pixels = new double[_pixelsData.Length];

            _pixelsData.CopyTo(pixels, 0);

            var clone = new ZsImage(pixels, Width, Height, NumberOfComponents);

            return(clone);
        }
Example #4
0
        public static ZsImage PyramidDownArgb(this ZsImage argbImage, Area2D filterArea, bool blur = true)
        {
            if (blur)
            {
                argbImage = argbImage.Filter(filterArea, GaussianFilter, 5, 5, 1.0 / 16.0);
            }

            argbImage = argbImage.ScaleDown2x();
            return(argbImage);
        }
        private static unsafe ZsImage MergeAlphaWithBackground(this ZsImage argbImage, double[] background)
        {
            if (argbImage == null)
            {
                throw new ArgumentNullException();
            }

            const int NotDividableMinAmountElements = 80;

            int pointsAmount = argbImage.Width * argbImage.Height;

            double[] pixelsData = argbImage.PixelsData;

            // Decide on how many partitions we should divade the processing
            // of the elements.
            var partsCount = pointsAmount > NotDividableMinAmountElements
                ? Environment.ProcessorCount
                : 1;

            var partSize = (int)(pointsAmount / partsCount);

            Parallel.For(0, partsCount, partIndex =>
            {
                var firstPointIndex = partIndex * partSize;
                var lastPointIndex  = firstPointIndex + partSize - 1;
                if (partIndex == partsCount - 1)
                {
                    lastPointIndex = pointsAmount - 1;
                }
                if (lastPointIndex > pointsAmount)
                {
                    lastPointIndex = pointsAmount - 1;
                }

                fixed(double *pixelsDataP = pixelsData)
                {
                    double alpha  = 0.0;
                    double nalpha = 1.0;

                    for (int pointIndex = lastPointIndex; pointIndex >= firstPointIndex; pointIndex--)
                    {
                        int i = pointIndex * 4;

                        // components should be in the range [0.0 , 1.0]
                        alpha  = *(pixelsDataP + i);
                        nalpha = 1.0 - alpha;
                        *(pixelsDataP + i + 1) = alpha * *(pixelsDataP + i + 1) + nalpha * background[0];
                        *(pixelsDataP + i + 2) = alpha * *(pixelsDataP + i + 2) + nalpha * background[1];
                        *(pixelsDataP + i + 3) = alpha * *(pixelsDataP + i + 3) + nalpha * background[2];
                    }
                }
            });

            return(argbImage);
        }
Example #6
0
        public static unsafe ZsImage ToRgbImage(this Nnf nnf)
        {
            const int NotDividableMinAmountElements = 80;
            var       nnfItems = nnf.GetNnfItems();
            var       width    = nnf.DstWidth;
            var       height   = nnf.DstHeight;

            var pointsAmount = width * height;

            var rgb = new double[pointsAmount * 3];

            // Decide on how many partitions we should divade the processing
            // of the elements.
            var partsCount = pointsAmount > NotDividableMinAmountElements
                ? Environment.ProcessorCount
                : 1;

            var partSize = (int)(pointsAmount / partsCount);

            Parallel.For(0, partsCount, partIndex =>
            {
                var firstPointIndex = partIndex * partSize;
                var lastPointIndex  = firstPointIndex + partSize - 1;
                if (partIndex == partsCount - 1)
                {
                    lastPointIndex = pointsAmount - 1;
                }
                if (lastPointIndex > pointsAmount)
                {
                    lastPointIndex = pointsAmount - 1;
                }

                fixed(double *nnfItemsP = nnfItems)
                fixed(double *rgbP      = rgb)
                {
                    var maxY = nnf.SourceHeight;
                    var maxX = nnf.SourceWidth;
                    var maxD = nnf.PatchSize * 100;

                    for (var pointIndex = firstPointIndex; pointIndex <= lastPointIndex; pointIndex++)
                    {
                        var nnfindex = (pointIndex / width) * width * 2 + (pointIndex % width) * 2;
                        var index    = *(nnfItemsP + nnfindex + 0);
                        var distance = nnfItems[nnfindex + 1];
                        *(rgbP + pointIndex * 3 + 0) = (double)(((int)index) % maxX) / maxX;
                        *(rgbP + pointIndex * 3 + 1) = (double)(((int)index) / maxX) / maxY;
                        *(rgbP + pointIndex * 3 + 2) = distance / maxD;
                    }
                }
            });
            var result = new ZsImage(rgb, width, height, 3);

            return(result);
        }
        private static unsafe void GrayToRgb(ZsImage grayImage)
        {
            if (grayImage == null)
            {
                throw new ArgumentNullException();
            }

            grayImage.InsertComponents(new[] { 0.0, 0.0 }, 1);

            const int NotDividableMinAmountElements = 80;

            double[] pixelsData = grayImage.PixelsData;

            int pointsAmount = grayImage.Width * grayImage.Height;

            // Decide on how many partitions we should divade the processing
            // of the elements.
            var partsCount = pointsAmount > NotDividableMinAmountElements
                ? Environment.ProcessorCount
                : 1;

            var partSize = (int)(pointsAmount / partsCount);

            Parallel.For(0, partsCount, partIndex =>
            {
                var firstPointIndex = partIndex * partSize;
                var lastPointIndex  = firstPointIndex + partSize - 1;
                if (partIndex == partsCount - 1)
                {
                    lastPointIndex = pointsAmount - 1;
                }
                if (lastPointIndex > pointsAmount)
                {
                    lastPointIndex = pointsAmount - 1;
                }

                fixed(double *pixelsDataP = pixelsData)
                {
                    for (int pointIndex = lastPointIndex; pointIndex >= firstPointIndex; pointIndex--)
                    {
                        // Step 1. Inverse Companding
                        int i = pointIndex * 3;

                        // components should be in the range [0.0 , 1.0]
                        double gray = *(pixelsDataP + i + 0);

                        //*(pixelsDataP + i + 0) = gray;
                        *(pixelsDataP + i + 1) = gray;
                        *(pixelsDataP + i + 2) = gray;
                    }
                }
            });
        }
Example #8
0
        public static Area2D FromArgbToArea2D(this ZsImage argbImage)
        {
            //TODO: check the ColorSpace not the components amount
            if (argbImage.NumberOfComponents < 4)
            {
                throw new ArgumentException("Image in ARGB color space is required.");
            }

            var width  = argbImage.Width;
            var height = argbImage.Height;
            var pixelsToFilterAmout = width * height;
            var componentsAmount    = argbImage.NumberOfComponents;
            var pixelsData          = argbImage.PixelsData;

            var pixelsArea = new byte[height][];

            for (int y = 0; y < height; y++)
            {
                pixelsArea[y] = new byte[width];
            }

            var partsCount = pixelsToFilterAmout > NotDividableMinAmountElements
                ? ThreadsCount
                : 1;
            var partSize = pixelsToFilterAmout / partsCount;

            //Parallel.For(0, partsCount, partIndex =>
            for (int partIndex = 0; partIndex < partsCount; partIndex++)
            {
                var firstPointIndex = partIndex * partSize;
                var lastPointIndex  = firstPointIndex + partSize - 1;
                if (partIndex == partsCount - 1)
                {
                    lastPointIndex = pixelsToFilterAmout - 1;
                }
                if (lastPointIndex > pixelsData.Length)
                {
                    lastPointIndex = pixelsToFilterAmout - 1;
                }

                for (int ii = firstPointIndex; ii <= lastPointIndex; ii++)
                {
                    if (pixelsData[ii * componentsAmount] > 0)
                    {
                        pixelsArea[ii / width][ii % width] = 1;
                    }
                }
            }
            //);

            return(Area2D.Create(0, 0, pixelsArea));
        }
        private static unsafe void RgbToGray(ZsImage rgbImage)
        {
            if (rgbImage == null)
            {
                throw new ArgumentNullException();
            }

            const int NotDividableMinAmountElements = 80;

            double[] pixelsData = rgbImage.PixelsData;

            int pointsAmount = rgbImage.Width * rgbImage.Height;

            // Decide on how many partitions we should divade the processing
            // of the elements.
            var partsCount = pointsAmount > NotDividableMinAmountElements
                ? Environment.ProcessorCount
                : 1;

            var partSize = (int)(pointsAmount / partsCount);

            Parallel.For(0, partsCount, partIndex =>
            {
                var firstPointIndex = partIndex * partSize;
                var lastPointIndex  = firstPointIndex + partSize - 1;
                if (partIndex == partsCount - 1)
                {
                    lastPointIndex = pointsAmount - 1;
                }
                if (lastPointIndex > pointsAmount)
                {
                    lastPointIndex = pointsAmount - 1;
                }

                fixed(double *pixelsDataP = pixelsData)
                {
                    for (int pointIndex = lastPointIndex; pointIndex >= firstPointIndex; pointIndex--)
                    {
                        int i = pointIndex * 3;

                        // components should be in the range [0.0 , 1.0]
                        double R = *(pixelsDataP + i + 0);
                        double G = *(pixelsDataP + i + 1);
                        double B = *(pixelsDataP + i + 2);

                        *(pixelsDataP + i + 0) = R * 0.2989 + G * 0.5870 + B * 0.1140;
                    }
                }
            });

            rgbImage.RemoveComponents(1, 2);
        }
Example #10
0
        public static ZsImage PyramidUpLab(this ZsImage labImage)
        {
            labImage = labImage
                       .FromLabToRgb()
                       //.FromRgbToArgb()
                       .ScaleUp2x()
                       .Filter(GaussianFilter, 5, 5, 4.0 / 16.0)
                       //.Filter(GaussianFilter3x3, 3, 3)
                       //.FromArgbToRgb()
                       .FromRgbToLab();

            return(labImage);
        }
Example #11
0
        public static ZsImage CopyFromImage(this ZsImage destImage, Area2D destArea, ZsImage srcImage, Area2D srcArea)
        {
            if (destImage.NumberOfComponents != srcImage.NumberOfComponents)
            {
                throw new DifferentImageFormatException();
            }

            var destImageArea = Area2D.Create(0, 0, destImage.Width, destImage.Height);
            var srcImageArea  = Area2D.Create(0, 0, srcImage.Width, srcImage.Height);

            // move areas to origin and intersect them
            var oDestArea = destArea
                            .Intersect(destImageArea)
                            .Translate(-destArea.Bound.X, -destArea.Bound.Y);

            var oSrcArea = srcArea
                           .Intersect(srcImageArea)
                           .Translate(-srcArea.Bound.X, -srcArea.Bound.Y);

            var intersection = oDestArea.Intersect(oSrcArea);

            // move 2 intersected areas back
            destArea = intersection.Translate(destArea.Bound.X, destArea.Bound.Y);
            srcArea  = intersection.Translate(srcArea.Bound.X, srcArea.Bound.Y);


            // copy pixels from intersection to intersection
            var destPixelIndecies = new int[destArea.ElementsCount];
            var srcPixelIndecies  = new int[srcArea.ElementsCount];

            destArea.FillMappedPointsIndexes(destPixelIndecies, destImage.Width);
            srcArea.FillMappedPointsIndexes(srcPixelIndecies, srcImage.Width);

            var dstPixelsData = destImage.PixelsData;
            var srcPixelsData = srcImage.PixelsData;

            //TODO: Speedup using multiple threads and pointers
            for (int i = 0; i < destPixelIndecies.Length; i++)
            {
                var dstPixelIndex = destPixelIndecies[i];
                var srcPixelIndex = srcPixelIndecies[i];

                for (int j = 0; j < destImage.NumberOfComponents; j++)
                {
                    dstPixelsData[dstPixelIndex * destImage.NumberOfComponents + j] =
                        srcPixelsData[srcPixelIndex * destImage.NumberOfComponents + j];
                }
            }

            return(destImage);
        }
Example #12
0
        public static ZsImage Filter(this ZsImage argbImage, Area2D filterArea, double[] filter, byte filterWidth, byte filterHeight, double multiplicator = 1.0)
        {
            if (filterWidth * filterHeight != filter.Length)
            {
                throw new ArgumentOutOfRangeException("The passed size of the filter doesn't match the filter size.");
            }

            var imageBoundArea = Area2D.Create(0, 0, argbImage.Width, argbImage.Height);

            filterArea = filterArea
                         .Intersect(imageBoundArea);

            // The filter should be applied to the specified area of interest
            argbImage.FilterArea(filterArea, filter, filterWidth, filterHeight, multiplicator);

            return(argbImage);
        }
Example #13
0
 public static ZsImage PyramidDownLab(this ZsImage labImage)
 {
     return(labImage.PyramidDownLab(true));
 }
Example #14
0
        private static void FilterArea(this ZsImage image, Area2D area, double[] filter, byte filterWidth, byte filterHeight, double multiplicator = 1.0)
        {
            if (filterWidth * filterHeight != filter.Length)
            {
                throw new ArgumentOutOfRangeException("The passed size of the filter doesn't match the filter size.");
            }

            var componentsAmount    = image.NumberOfComponents;
            var imageWidth          = image.Width;
            var imageHeight         = image.Height;
            var pixelsToFilterAmout = area.ElementsCount;
            var resultPixelsData    = image.PixelsData;

            var pixelsToFilterIndices = new int[pixelsToFilterAmout];

            area.FillMappedPointsIndexes(pixelsToFilterIndices, imageWidth);

            var pixelsData = new double[resultPixelsData.Length];

            resultPixelsData.CopyTo(pixelsData, 0);
            byte offs = (byte)(filterWidth / 2);

            var partsCount = pixelsToFilterAmout > NotDividableMinAmountElements
                ? ThreadsCount
                : 1;
            var partSize = pixelsToFilterAmout / partsCount;

            //Parallel.For(0, partsCount, partIndex =>
            for (int partIndex = 0; partIndex < partsCount; partIndex++)
            {
                var pixelsToFilterIndicesSet = new HashSet <int>(pixelsToFilterIndices);
                var pixel = new double[componentsAmount];

                var firstPointIndex = partIndex * partSize;
                var lastPointIndex  = firstPointIndex + partSize - 1;
                if (partIndex == partsCount - 1)
                {
                    lastPointIndex = pixelsToFilterAmout - 1;
                }
                if (lastPointIndex > pixelsData.Length)
                {
                    lastPointIndex = pixelsToFilterAmout - 1;
                }

                for (int ii = firstPointIndex; ii <= lastPointIndex; ii++)
                {
                    int pixelIndex = pixelsToFilterIndices[ii];

                    int ix = pixelIndex % imageWidth;
                    int iy = pixelIndex / imageWidth;

                    var sum = 0.0;

                    for (int fy = -offs; fy <= offs; fy++)
                    {
                        for (int fx = -offs; fx <= offs; fx++)
                        {
                            int x = ix + fx;
                            int y = iy + fy;

                            if (x < 0 || imageWidth <= x ||
                                y < 0 || imageHeight <= y)
                            {
                                continue;
                            }

                            int neighbourIndex = x + y * imageWidth;

                            if (!pixelsToFilterIndicesSet.Contains(neighbourIndex))
                            {
                                continue;
                            }

                            var filterVal = filter[(fx + offs) + (fy + offs) * filterWidth] * multiplicator;
                            sum += filterVal;

                            var pi = y * imageWidth + x;
                            var j  = pi * componentsAmount;

                            for (int c = 0; c < componentsAmount; c++)
                            {
                                pixel[c] += pixelsData[j + c] * filterVal;
                            }
                        }
                    }

                    if (sum <= 0)
                    {
                        sum = 1.0;
                    }

                    var pixelPosition = pixelIndex * componentsAmount;

                    for (int c = 0; c < componentsAmount; c++)
                    {
                        resultPixelsData[pixelPosition + c] = pixel[c] / sum;
                        if (resultPixelsData[pixelPosition + c] > 1)
                        {
                            resultPixelsData[pixelPosition + c] = 1.0;
                        }
                        if (resultPixelsData[pixelPosition + c] < 0)
                        {
                            resultPixelsData[pixelPosition + c] = 0.0;
                        }
                        pixel[c] = 0;
                    }
                }
            }
            //);
        }
        public static unsafe ZsImage SetComponentsValues(this ZsImage image, Area2D opaqueArea, double[] values, byte index)
        {
            if (image == null)
            {
                throw new ArgumentNullException();
            }

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

            if (values.Length == 0)
            {
                throw new ArgumentException("values can not be empty", nameof(values));
            }

            if (index >= image.NumberOfComponents)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }

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

            const int NotDividableMinAmountElements = 80;

            var imageArea = Area2D.Create(0, 0, image.Width, image.Height);

            opaqueArea = opaqueArea.Intersect(imageArea);
            if (!opaqueArea.IsEmpty)
            {
                byte componentsAmount = image.NumberOfComponents;
                int  pointsAmount     = opaqueArea.ElementsCount;
                int  valuesAmount     = componentsAmount >= index + values.Length
                    ? values.Length
                    : values.Length - ((index + values.Length) - componentsAmount);

                double[] pixelsData = image.PixelsData;

                var pointIndices = new int[opaqueArea.ElementsCount];
                opaqueArea.FillMappedPointsIndexes(pointIndices, image.Width);

                // Decide on how many partitions we should divade the processing
                // of the elements.
                var partsCount = pointsAmount > NotDividableMinAmountElements
                    ? Environment.ProcessorCount
                    : 1;

                var partSize = (int)(pointsAmount / partsCount);

                Parallel.For(0, partsCount, partIndex =>
                {
                    var firstPointIndex = partIndex * partSize;
                    var lastPointIndex  = firstPointIndex + partSize - 1;
                    if (partIndex == partsCount - 1)
                    {
                        lastPointIndex = pointsAmount - 1;
                    }
                    if (lastPointIndex > pointsAmount)
                    {
                        lastPointIndex = pointsAmount - 1;
                    }

                    fixed(double *pixelsDataP = pixelsData)
                    {
                        for (int pointIndex = lastPointIndex; pointIndex >= firstPointIndex; pointIndex--)
                        {
                            int i = pointIndices[pointIndex] * componentsAmount;

                            for (int j = 0; j < valuesAmount; j++)
                            {
                                *(pixelsDataP + i + j + index) = values[j];
                            }
                        }
                    }
                });
            }
            return(image);
        }
        private static unsafe void RgbToLab(ZsImage rgbImage)
        {
            if (rgbImage == null)
            {
                throw new ArgumentNullException();
            }

            const double K1 = 1.0 / 1.055;
            const double K2 = 1.0 / 12.92;

            const double Xr = 1.0 / 95.047;
            const double Yr = 1.0 / 100.0;
            const double Zr = 1.0 / 108.883;

            const int NotDividableMinAmountElements = 80;

            double[] pixelsData = rgbImage.PixelsData;

            int pointsAmount = rgbImage.Width * rgbImage.Height;

            // Decide on how many partitions we should divade the processing
            // of the elements.
            var partsCount = pointsAmount > NotDividableMinAmountElements
                ? Environment.ProcessorCount
                : 1;

            var partSize = (int)(pointsAmount / partsCount);

            Parallel.For(0, partsCount, partIndex =>
            {
                var firstPointIndex = partIndex * partSize;
                var lastPointIndex  = firstPointIndex + partSize - 1;
                if (partIndex == partsCount - 1)
                {
                    lastPointIndex = pointsAmount - 1;
                }
                if (lastPointIndex > pointsAmount)
                {
                    lastPointIndex = pointsAmount - 1;
                }

                fixed(double *pixelsDataP = pixelsData)
                {
                    for (int pointIndex = lastPointIndex; pointIndex >= firstPointIndex; pointIndex--)
                    {
                        // Step 1. Inverse Companding
                        int i = pointIndex * 3;

                        // components should be in the range [0.0 , 1.0]
                        double R = *(pixelsDataP + i + 0);
                        double G = *(pixelsDataP + i + 1);
                        double B = *(pixelsDataP + i + 2);

                        // Inverse sRBG Companding http://www.brucelindbloom.com/index.html?Math.html
                        var r = R > 0.04045 ? SMath.Pow((R + 0.055) * K1, 2.4) * 100.0 : R * K2 * 100.0;
                        var g = G > 0.04045 ? SMath.Pow((G + 0.055) * K1, 2.4) * 100.0 : G * K2 * 100.0;
                        var b = B > 0.04045 ? SMath.Pow((B + 0.055) * K1, 2.4) * 100.0 : B * K2 * 100.0;

                        // Step 2. Linear RGB to XYZ
                        double xr = (r * 0.4124 + g * 0.3576 + b * 0.1805) * Xr;
                        double yr = (r * 0.2126 + g * 0.7152 + b * 0.0722) * Yr;
                        double zr = (r * 0.0193 + g * 0.1192 + b * 0.9505) * Zr;

                        double fx = xr > e ? SMath.Pow(xr, OneThird) : (k * xr) + S;
                        double fy = yr > e ? SMath.Pow(yr, OneThird) : (k * yr) + S;
                        double fz = zr > e ? SMath.Pow(zr, OneThird) : (k * zr) + S;

                        *(pixelsDataP + i + 0) = 116.0 * fy - 16.0;
                        *(pixelsDataP + i + 1) = 500.0 * (fx - fy);
                        *(pixelsDataP + i + 2) = 200.0 * (fy - fz);
                    }
                }
            });
        }
Example #17
0
        /// <summary>
        /// Converts Bitmap to the ZsImage in ARGB format.
        /// </summary>
        /// <param name="bitmap">The bitmap.</param>
        /// <returns></returns>
        public static unsafe ZsImage ToArgbImage(this Bitmap bitmap)
        {
            var width  = bitmap.Width;
            var height = bitmap.Height;

            var components = new double[4 * width * height];

            const double N = 1.0 / 255.0;

            BitmapData bd = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.ReadOnly,
                                            PixelFormat.Format32bppArgb);

            fixed(double *componentsP = components)
            {
                try
                {
                    byte *curpos = (byte *)bd.Scan0;
                    //TODO: invert and paralelize
                    for (int i = 0; i < components.Length; i += 4)
                    {
                        // components should be in the range [0.0 , 1.0]
                        // but we currently have them in the [0, 255] range
                        double B = (*(curpos++)) * N;
                        double G = (*(curpos++)) * N;
                        double R = (*(curpos++)) * N;
                        double A = (*(curpos++)) * N;

                        if (A < 0)
                        {
                            A = 0;
                        }
                        else if (A > 1)
                        {
                            A = 1;
                        }

                        if (R < 0)
                        {
                            R = 0;
                        }
                        else if (R > 1)
                        {
                            R = 1;
                        }

                        if (G < 0)
                        {
                            G = 0;
                        }
                        else if (G > 1)
                        {
                            G = 1;
                        }

                        if (B < 0)
                        {
                            B = 0;
                        }
                        else if (B > 1)
                        {
                            B = 1;
                        }

                        *(componentsP + i + 0) = A;
                        *(componentsP + i + 1) = R;
                        *(componentsP + i + 2) = G;
                        *(componentsP + i + 3) = B;
                    }
                }
                finally
                {
                    bitmap.UnlockBits(bd);
                }
            }

            var result = new ZsImage(components, width, height, 4);

            return(result);
        }
        private static unsafe void LabToRgb(ZsImage labImage)
        {
            //LabToXyz(ref labImage);
            if (labImage == null)
            {
                throw new ArgumentNullException();
            }

            double[] pixelsData = labImage.PixelsData;

            const int    NotDividableMinAmountElements = 80;
            const double Xr = 95.047;
            const double Yr = 100.000;
            const double Zr = 108.883;

            const double K1 = 1.0 / 116.0;
            const double K2 = 1.0 / 500.0;
            const double K3 = 1.0 / 200.0;
            const double K4 = 1.0 / k;
            const double W  = 0.0031308;

            const double Xr2 = 1.0 / 100.0;
            const double Yr2 = 1.0 / 100.0;
            const double Zr2 = 1.0 / 100.0;

            int pointsAmount = labImage.Width * labImage.Height;

            // Decide on how many partitions we should divade the processing
            // of the elements.
            var partsCount = pointsAmount > NotDividableMinAmountElements
                ? Environment.ProcessorCount
                : 1;

            var partSize = (int)(pointsAmount / partsCount);

            Parallel.For(0, partsCount, partIndex =>
            {
                var firstPointIndex = partIndex * partSize;
                var lastPointIndex  = firstPointIndex + partSize - 1;
                if (partIndex == partsCount - 1)
                {
                    lastPointIndex = pointsAmount - 1;
                }
                if (lastPointIndex > pointsAmount)
                {
                    lastPointIndex = pointsAmount - 1;
                }

                fixed(double *pixelsDataP = pixelsData)
                {
                    for (int pointIndex = lastPointIndex; pointIndex >= firstPointIndex; pointIndex--)
                    {
                        // Step 1. Inverse Companding
                        int i = pointIndex * 3;

                        double L  = *(pixelsDataP + i + 0);
                        double fy = (L + 16.0) * K1;
                        double fx = (*(pixelsDataP + i + 1) * K2) + fy;
                        double fz = fy - (*(pixelsDataP + i + 2) * K3);

                        var yr = fy * fy * fy;
                        if (yr <= e)
                        {
                            yr = (fy - S) * K4;
                        }
                        var xr = fx * fx * fx;
                        if (xr <= e)
                        {
                            xr = (fx - S) * K4;
                        }
                        var zr = fz * fz * fz;
                        if (zr <= e)
                        {
                            zr = (fz - S) * K4;
                        }

                        double X = xr * Xr * Xr2;
                        double Y = yr * Yr * Yr2;
                        double Z = zr * Zr * Zr2;

                        // Step 1.  XYZ to Linear RGB
                        double r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
                        double g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
                        double b = X * 0.0557 + Y * -0.2040 + Z * 1.0570;

                        // Step 2.  Companding
                        // sRGB Companding
                        *(pixelsDataP + i + 0) = r > W ? 1.055 * SMath.Pow(r, S2) - 0.055 : 12.92 * r;
                        *(pixelsDataP + i + 1) = g > W ? 1.055 * SMath.Pow(g, S2) - 0.055 : 12.92 * g;
                        *(pixelsDataP + i + 2) = b > W ? 1.055 * SMath.Pow(b, S2) - 0.055 : 12.92 * b;
                    }
                }
            });
        }
 public static ZsImage FromArgbToRgb(this ZsImage argbImage, double[] background)
 {
     return(argbImage
            .MergeAlphaWithBackground(background)
            .RemoveComponents(0));
 }
Example #20
0
        public static unsafe ZsImage RestoreImage(this Nnf nnf, ZsImage image, byte componentsCount, byte patchSize)
        {
            const int NotDividableMinAmountElements = 80;

            var width    = nnf.DstWidth;
            var height   = nnf.DstHeight;
            var nnfItems = nnf.GetNnfItems();

            double destWidth  = width;
            double destHeight = height;

            double sourceWidth  = image.Width;
            double sourceHeight = image.Height;

            int patchOffs = (patchSize - 1) / 2;

            var result        = new double[width * height * componentsCount];
            var srcPixelsData = image.PixelsData;
            var pointsAmount  = width * height;

            // Decide on how many partitions we should divade the processing
            // of the elements.
            var partsCount = pointsAmount > NotDividableMinAmountElements
                ? Environment.ProcessorCount
                : 1;

            var partSize = (int)(pointsAmount / partsCount);

            Parallel.For(0, partsCount, partIndex =>
            {
                var firstPointIndex = partIndex * partSize;
                var lastPointIndex  = firstPointIndex + partSize - 1;
                if (partIndex == partsCount - 1)
                {
                    lastPointIndex = pointsAmount - 1;
                }
                if (lastPointIndex > pointsAmount)
                {
                    lastPointIndex = pointsAmount - 1;
                }

                var color = new double[componentsCount];

                fixed(double *resultP    = result)
                fixed(double *srcPixelsP = srcPixelsData)
                fixed(double *colorP     = color)
                fixed(double *nnfItemsP  = nnfItems)
                {
                    for (var pointIndex = firstPointIndex; pointIndex <= lastPointIndex; pointIndex++)
                    {
                        int count = 0;

                        int y = pointIndex / width;
                        int x = pointIndex % width;

                        //go thru the patch
                        for (int py = y - patchOffs, yi = 0; yi < patchSize; py++, yi++)
                        {
                            for (int px = x - patchOffs, xi = 0; xi < patchSize; px++, xi++)
                            {
                                if ((0 <= py && py < destHeight && 0 <= px && px < destWidth))
                                {
                                    var deltaX = xi - patchOffs;
                                    var deltaY = yi - patchOffs;

                                    var index           = (int)*(nnfItemsP + py * width * 2 + px * 2);
                                    var sourcePixelPosX = index % nnf.SourceWidth - deltaX;
                                    var sourcePixelPosY = index / nnf.SourceWidth - deltaY;

                                    if ((0 <= sourcePixelPosY && sourcePixelPosY < sourceHeight &&
                                         0 <= sourcePixelPosX && sourcePixelPosX < sourceWidth))
                                    {
                                        var ppos = (sourcePixelPosY * (int)sourceWidth + sourcePixelPosX) * componentsCount;
                                        for (int j = 0; j < componentsCount; j++)
                                        {
                                            *(colorP + j) += *(srcPixelsP + ppos + j);
                                        }
                                        count++;
                                    }
                                }
                            }
                        }

                        var pos = (y * width + x) * componentsCount;
                        for (int j = 0; j < componentsCount; j++)
                        {
                            *(resultP + pos + j) = *(colorP + j) / count;
                            *(colorP + j)        = 0;
                        }
                    }
                }
            });

            return(new ZsImage(result, width, height, componentsCount));
        }
Example #21
0
        public static ZsImage RestoreRgbImage(this Nnf nnf, ZsImage image, byte componentsCount, byte patchSize)
        {
            var lab = nnf.RestoreImage(image, componentsCount, patchSize);

            return(lab.FromLabToRgb());
        }
 public static ZsImage FromGrayToRgb(this ZsImage grayImage)
 {
     GrayToRgb(grayImage);
     return(grayImage);
 }
 public static ZsImage FromRgbToLab(this ZsImage image)
 {
     RgbToLab(image);
     return(image);
 }
Example #24
0
        /// <summary>
        /// Converts Bitmap into ZsImage in the RGB format.
        /// </summary>
        /// <param name="bitmap">The bitmap.</param>
        /// <returns></returns>
        public static unsafe ZsImage ToRgbImage(this Bitmap bitmap)
        {
            var width  = bitmap.Width;
            var height = bitmap.Height;

            var components = new double[3 * width * height];

            /*
             * var pixelsArea = new byte[height][];
             * for (int y = 0; y < height; y++)
             * {
             *  pixelsArea[y] = new byte[width];
             * }
             *
             * var isSemiTransparent = false;
             */

            const double N = 1.0 / 255.0;

            BitmapData bd = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.ReadOnly,
                                            PixelFormat.Format32bppArgb);

            fixed(double *componentsP = components)
            {
                try
                {
                    byte *curpos = (byte *)bd.Scan0;
                    //TODO: invert and paralelize
                    for (int i = 0; i < components.Length; i += 3)
                    {
                        // components should be in the range [0.0 , 1.0]
                        // but we currently have them in the [0, 255] range
                        double B = (*(curpos++)) * N;
                        double G = (*(curpos++)) * N;
                        double R = (*(curpos++)) * N;
                        curpos++;

                        /*
                         * double A = (*(curpos++)) * N;
                         *
                         * if (A != 0)
                         * {
                         *  pixelsArea[(i / 3) / width][(i / 3) % width] = 1;
                         * }
                         * else isSemiTransparent = true;
                         */

                        if (R < 0)
                        {
                            R = 0;
                        }
                        else if (R > 1)
                        {
                            R = 1;
                        }

                        if (G < 0)
                        {
                            G = 0;
                        }
                        else if (G > 1)
                        {
                            G = 1;
                        }

                        if (B < 0)
                        {
                            B = 0;
                        }
                        else if (B > 1)
                        {
                            B = 1;
                        }

                        *(componentsP + i + 0) = R;
                        *(componentsP + i + 1) = G;
                        *(componentsP + i + 2) = B;
                    }
                }
                finally
                {
                    bitmap.UnlockBits(bd);
                }
            }

            //if (isSemiTransparent)
            //{
            //    var area = Area2D.Create(0, 0, pixelsArea);
            //    result = new ImageProcessing.ZsImage(components, area, width, height, 3);
            //}
            //else
            var result = new ZsImage(components, width, height, 3);

            return(result);
        }
Example #25
0
        public static ZsImage PyramidDownArgb(this ZsImage argbImage, bool blur = true)
        {
            var filterArea = Area2D.Create(0, 0, argbImage.Width, argbImage.Height);

            return(argbImage.PyramidDownArgb(filterArea, blur));
        }
Example #26
0
        /// <summary>
        /// Converts ZsImage in ARGB format into the Bitmap.
        /// </summary>
        /// <param name="argbImage">The ARGB image.</param>
        /// <returns></returns>
        public static unsafe Bitmap FromArgbToBitmap(this ZsImage argbImage)
        {
            var width  = argbImage.Width;
            var height = argbImage.Height;

            double[] pixelsData       = argbImage.PixelsData;
            var      componentsAmount = argbImage.NumberOfComponents;

            Bitmap result = new Bitmap(width, height, PixelFormat.Format32bppArgb);

            BitmapData bd = result.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

            fixed(double *componentsP = pixelsData)
            {
                try
                {
                    byte *curpos = (byte *)bd.Scan0;
                    for (int i = 0; i < pixelsData.Length; i += componentsAmount)
                    {
                        byte A = (byte)(*(componentsP + i + 0) * 255);
                        byte R = (byte)(*(componentsP + i + 1) * 255);
                        byte G = (byte)(*(componentsP + i + 2) * 255);
                        byte B = (byte)(*(componentsP + i + 3) * 255);

                        if (A < 0)
                        {
                            A = 0;
                        }
                        else if (A > 255)
                        {
                            A = 255;
                        }

                        if (R < 0)
                        {
                            R = 0;
                        }
                        else if (R > 255)
                        {
                            R = 255;
                        }

                        if (G < 0)
                        {
                            G = 0;
                        }
                        else if (G > 255)
                        {
                            G = 255;
                        }

                        if (B < 0)
                        {
                            B = 0;
                        }
                        else if (B > 255)
                        {
                            B = 255;
                        }

                        *(curpos++) = B;
                        *(curpos++) = G;
                        *(curpos++) = R;
                        *(curpos++) = A;
                    }
                }
                finally
                {
                    result.UnlockBits(bd);
                }
            }

            return(result);
        }
 public static ZsImage FromLabToRgb(this ZsImage image)
 {
     LabToRgb(image);
     return(image);
 }
Example #28
0
        public static ZsImage Filter(this ZsImage argbImage, double[] filter, byte filterWidth, byte filterHeight, double multiplicator = 1.0)
        {
            var area = Area2D.Create(0, 0, argbImage.Width, argbImage.Height);

            return(argbImage.Filter(area, filter, filterWidth, filterHeight, multiplicator));
        }
Example #29
0
        /// <summary>
        /// Converts ZsImage in RGB format to the Bitmap image.
        /// </summary>
        /// <param name="rgbImage">The RGB image.</param>
        /// <returns></returns>
        public static unsafe Bitmap FromRgbToBitmap(this ZsImage rgbImage)
        {
            var width  = rgbImage.Width;
            var height = rgbImage.Height;

            double[] pixelsData = rgbImage.PixelsData;

            Bitmap result = new Bitmap(width, height, PixelFormat.Format32bppArgb);

            BitmapData bd = result.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

            fixed(double *pixelsDataP = pixelsData)
            {
                try
                {
                    byte *curpos = (byte *)bd.Scan0;
                    for (int i = 0; i < pixelsData.Length; i += 3)
                    //for (int ii = 0; ii < pixelIndices.Length; ii++)
                    {
                        //int i = pixelIndices[ii]*3;

                        byte A = 255;
                        byte R = (byte)(*(pixelsDataP + i + 0) * 255);
                        byte G = (byte)(*(pixelsDataP + i + 1) * 255);
                        byte B = (byte)(*(pixelsDataP + i + 2) * 255);

                        if (R < 0)
                        {
                            R = 0;
                        }
                        else if (R > 255)
                        {
                            R = 255;
                        }

                        if (G < 0)
                        {
                            G = 0;
                        }
                        else if (G > 255)
                        {
                            G = 255;
                        }

                        if (B < 0)
                        {
                            B = 0;
                        }
                        else if (B > 255)
                        {
                            B = 255;
                        }

                        *(curpos++) = B;
                        *(curpos++) = G;
                        *(curpos++) = R;
                        *(curpos++) = A;
                    }
                }
                finally
                {
                    result.UnlockBits(bd);
                }
            }

            return(result);
        }
 public static ZsImage FromRgbToArgb(this ZsImage rgbImage, Area2D opaqueArea)
 {
     return(rgbImage.InsertComponents(new[] { 0.0 }, 0)
            .SetComponentsValues(opaqueArea, new[] { 1.0 }, 0));
 }