예제 #1
0
 private void SetFilter()
 {
     FormFilter           = new OrderedDitheringFilter();
     FormFilter.Kernel    = Kernel;
     FormFilter.AnchorX   = (Rows - 1) / 2;
     FormFilter.AnchorY   = (Columns - 1) / 2;
     FormFilter.K         = K;
     FormFilter.Dimention = Rows;
 }
        public static Bitmap LabTask2(this Bitmap sourceBitmap, OrderedDitheringFilter filter, bool _flag)
        {
            BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            byte[] pixelBuffer  = new byte[sourceData.Stride * sourceData.Height];
            byte[] resultBuffer = new byte[sourceData.Stride * sourceData.Height];


            Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);


            sourceBitmap.UnlockBits(sourceData);



            int filterAnchorX    = filter.AnchorX;
            int filterAnchorY    = filter.AnchorY;
            int filterDimension  = filter.Dimention;
            int indexLowerBoundX = -filterAnchorX;
            int indexUpperBoundX = (filterDimension - filterAnchorX) - 1;
            int indexLowerBoundY = -filterAnchorY;
            int indexUpperBoundY = (filterDimension - filterAnchorY) - 1;
            int K = filter.K;

            double[] levels = new double[K];

            for (int i = 0; i < levels.Length; i++)
            {
                double interval = (float)i / (K - 1);
                levels[i] = interval * 255;
            }

            double[] levelsY  = new double[K];
            double[] levelsCr = new double[K];
            double[] levelsCb = new double[K];

            for (int i = 0; i < levelsY.Length; i++)
            {
                double interval = (float)i / (K - 1);
                levelsY[i] = 17 + interval * (235 - 17);
            }

            for (int i = 0; i < levelsCr.Length; i++)
            {
                double interval = (float)i / (K - 1);
                levelsCr[i] = 16 + interval * (240 - 16);
            }

            for (int i = 0; i < levelsCb.Length; i++)
            {
                double interval = (float)i / (K - 1);
                levelsCb[i] = 16 + interval * (240 - 16);
            }

            for (int offsetY = 0; offsetY < sourceBitmap.Height; offsetY += filter.Dimention)
            {
                for (int offsetX = 0; offsetX < sourceBitmap.Width; offsetX += filter.Dimention)
                {
                    int byteOffset = offsetY * sourceData.Stride + offsetX * 4;

                    for (int filterY = indexLowerBoundY; filterY <= indexUpperBoundY; filterY++)
                    {
                        int computeY = (filterY) * sourceData.Stride;

                        if ((offsetY + filterY < 0) || (offsetY + filterY) > (sourceBitmap.Height - 1))
                        {
                            continue;
                        }

                        for (int filterX = indexLowerBoundX; filterX <= indexUpperBoundX; filterX++)
                        {
                            int computeX = filterX * 4;

                            if ((offsetX + filterX) < 0 || (offsetX + filterX) > (sourceBitmap.Width - 1))
                            {
                                continue;
                            }

                            int calcOffset = byteOffset + computeY + computeX;

                            double kernelValue = filter.Kernel[filterY + filterAnchorY][filterX + filterAnchorX];


                            double blue  = (pixelBuffer[calcOffset]);
                            double green = (pixelBuffer[calcOffset + 1]);
                            double red   = (pixelBuffer[calcOffset + 2]);

                            double Y;
                            double Cb;
                            double Cr;

                            if (_flag)
                            {
                                Y  = red;
                                Cb = green;
                                Cr = blue;
                            }
                            else
                            {
                                Y  = 16.0 + 1.0 / 256.0 * (65.738 * red + 129.057 * green + 25.064 * blue);
                                Cb = 128.0 + 1.0 / 256.0 * (-37.945 * red - 74.494 * green + 112.439 * blue);
                                Cr = 128.0 + 1.0 / 256.0 * (112.439 * red - 94.154 * green - 18.285 * blue);
                            }

                            double newY  = levelsY[TakeLevelIndex(Y, kernelValue, K)];
                            double newCr = levelsCr[TakeLevelIndex(Cr, kernelValue, K)];
                            double newCb = levelsCb[TakeLevelIndex(Cb, kernelValue, K)];

                            double newRed = (298.082 * newY + 408.583 * newCr) / 256.0 - 222.921;
                            if (newRed < 0)
                            {
                                newRed = 0;
                            }
                            if (newRed > 255)
                            {
                                newRed = 255;
                            }

                            double newGreen = (298.082 * newY - 100.291 * newCb - 208.120 * newCr) / 256.0 + 135.576;
                            if (newGreen < 0)
                            {
                                newGreen = 0;
                            }
                            if (newGreen > 255)
                            {
                                newGreen = 255;
                            }

                            double newBlue = (298.082 * newY + 516.412 * newCb) / 256.0 - 276.836;
                            if (newBlue < 0)
                            {
                                newBlue = 0;
                            }
                            if (newBlue > 255)
                            {
                                newBlue = 255;
                            }

                            if (newGreen < 0)
                            {
                                newGreen = 0;
                            }

                            resultBuffer[calcOffset]     = (byte)newBlue;
                            resultBuffer[calcOffset + 1] = (byte)newGreen;
                            resultBuffer[calcOffset + 2] = (byte)newRed;


                            resultBuffer[calcOffset + 3] = 255;
                        }
                    }
                }
            }


            Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);

            BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

            Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length);
            resultBitmap.UnlockBits(resultData);

            return(resultBitmap);
        }
        public static Bitmap ApplyOrderedDithering(this Bitmap sourceBitmap, OrderedDitheringFilter filter)
        {
            BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            byte[] pixelBuffer  = new byte[sourceData.Stride * sourceData.Height];
            byte[] resultBuffer = new byte[sourceData.Stride * sourceData.Height];


            Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);


            sourceBitmap.UnlockBits(sourceData);



            int filterAnchorX    = filter.AnchorX;
            int filterAnchorY    = filter.AnchorY;
            int filterDimension  = filter.Dimention;
            int indexLowerBoundX = -filterAnchorX;
            int indexUpperBoundX = (filterDimension - filterAnchorX) - 1;
            int indexLowerBoundY = -filterAnchorY;
            int indexUpperBoundY = (filterDimension - filterAnchorY) - 1;
            int K = filter.K;

            double[] levels = new double[K];

            for (int i = 0; i < levels.Length; i++)
            {
                double interval = (float)i / (K - 1);
                levels[i] = interval * 255;
            }

            for (int offsetY = 0; offsetY < sourceBitmap.Height; offsetY += filter.Dimention)
            {
                for (int offsetX = 0; offsetX < sourceBitmap.Width; offsetX += filter.Dimention)
                {
                    int byteOffset = offsetY * sourceData.Stride + offsetX * 4;

                    for (int filterY = indexLowerBoundY; filterY <= indexUpperBoundY; filterY++)
                    {
                        int computeY = (filterY) * sourceData.Stride;

                        if ((offsetY + filterY < 0) || (offsetY + filterY) > (sourceBitmap.Height - 1))
                        {
                            continue;
                        }

                        for (int filterX = indexLowerBoundX; filterX <= indexUpperBoundX; filterX++)
                        {
                            int computeX = filterX * 4;

                            if ((offsetX + filterX) < 0 || (offsetX + filterX) > (sourceBitmap.Width - 1))
                            {
                                continue;
                            }

                            int calcOffset = byteOffset + computeY + computeX;

                            double kernelValue = filter.Kernel[filterY + filterAnchorY][filterX + filterAnchorX];
                            double blue        = (pixelBuffer[calcOffset]);
                            double green       = (pixelBuffer[calcOffset + 1]);
                            double red         = (pixelBuffer[calcOffset + 2]);

                            resultBuffer[calcOffset]     = (byte)levels[TakeLevelIndex(blue, kernelValue, K)];
                            resultBuffer[calcOffset + 1] = (byte)levels[TakeLevelIndex(green, kernelValue, K)];
                            resultBuffer[calcOffset + 2] = (byte)levels[TakeLevelIndex(red, kernelValue, K)];

                            resultBuffer[calcOffset + 3] = 255;
                        }
                    }
                }
            }


            Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);

            BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

            Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length);
            resultBitmap.UnlockBits(resultData);

            return(resultBitmap);
        }