/// <summary> /// Process the filter on the specified image /// </summary> /// /// <param name="sourceData">Source image data</param> /// <param name="destinationData">Destination image data</param> /// protected override unsafe void ProcessFilter(BitmapData sourceData, BitmapData destinationData) { byte *src = null; byte *dst = (byte *)destinationData.Scan0.ToPointer( ); // get width and height int width = sourceData.Width; int height = sourceData.Height; int widthM1 = width - 1; int heightM1 = height - 1; int stride = destinationData.Stride; int offset = stride - width; double ex, ey, weight, weightTotal = 0, total = 0; // convert image to grayscale if it is color Bitmap grayImage = null; BitmapData grayData = null; if (sourceData.PixelFormat != PixelFormat.Format8bppIndexed) { // create grayscale filter IFilter filter = new GrayscaleRMY( ); // do the processing grayImage = filter.Apply(sourceData); // lock the image grayData = grayImage.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); // set source pointer src = (byte *)grayData.Scan0.ToPointer( ); } else { src = (byte *)sourceData.Scan0.ToPointer( ); } // --- 1st pass - collecting statistics // skip the first line for the first pass src += stride; // for each line for (int y = 1; y < heightM1; y++) { src++; // for each pixels for (int x = 1; x < widthM1; x++, src++) { // the equations are: // ex = I(x + 1, y) - I(x - 1, y) // ey = I(x, y + 1) - I(x, y - 1) // weight = max(ex, ey) // weightTotal += weight // total += weight * I(x, y) ex = src[1] - src[-1]; ey = src[stride] - src[-stride]; weight = (ex > ey) ? ex : ey; weightTotal += weight; total += weight * (*src); } src += offset + 1; } // calculate threshold threshold = (weightTotal == 0) ? (byte)0 : (byte)(total / weightTotal); // --- 2nd pass - thresholding src = (grayData != null) ? (byte *)grayData.Scan0.ToPointer( ) : (byte *)sourceData.Scan0.ToPointer( ); // for each line for (int y = 0; y < height; y++) { // for all pixels for (int x = 0; x < width; x++, src++, dst++) { *dst = (byte)((*src <= threshold) ? 0 : 255); } src += offset; dst += offset; } // release gray image, if there was conversion if (grayData != null) { grayImage.UnlockBits(grayData); grayImage.Dispose( ); } }
/// <summary> /// Process the filter on the specified image /// </summary> /// /// <param name="sourceData">Source image data</param> /// <param name="destinationData">Destination image data</param> /// protected override unsafe void ProcessFilter(BitmapData sourceData, BitmapData destinationData) { byte *src = null; byte *dst = (byte *)destinationData.Scan0.ToPointer( ); // get width and height int width = sourceData.Width; int height = sourceData.Height; int widthM1 = width - 1; int heightM1 = height - 1; int stride = destinationData.Stride; int offset = stride - width; int d, max, v; // convert image to grayscale if it is color Bitmap grayImage = null; BitmapData grayData = null; if (sourceData.PixelFormat != PixelFormat.Format8bppIndexed) { // create grayscale filter IFilter filter = new GrayscaleRMY( ); // do the processing grayImage = filter.Apply(sourceData); // lock the image grayData = grayImage.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); // set source pointer src = (byte *)grayData.Scan0.ToPointer( ); } else { src = (byte *)sourceData.Scan0.ToPointer( ); } // do the processing job // skip one stride src += stride; dst += stride; // for each line for (int y = 1; y < heightM1; y++) { src++; dst++; // for each pixel for (int x = 1; x < widthM1; x++, src++, dst++) { max = 0; v = *src; // top-left d = v - src[-stride - 1]; if (d < 0) { d = -d; } if (d > max) { max = d; } // top d = v - src[-stride]; if (d < 0) { d = -d; } if (d > max) { max = d; } // top-right d = v - src[-stride + 1]; if (d < 0) { d = -d; } if (d > max) { max = d; } // left d = v - src[-1]; if (d < 0) { d = -d; } if (d > max) { max = d; } // right d = v - src[1]; if (d < 0) { d = -d; } if (d > max) { max = d; } // bottom-left d = v - src[stride - 1]; if (d < 0) { d = -d; } if (d > max) { max = d; } // bottom d = v - src[stride]; if (d < 0) { d = -d; } if (d > max) { max = d; } // bottom-right d = v - src[stride + 1]; if (d < 0) { d = -d; } if (d > max) { max = d; } *dst = (byte)max; } src += offset + 1; dst += offset + 1; } // release gray image, if there was conversion if (grayData != null) { grayImage.UnlockBits(grayData); grayImage.Dispose( ); } }
/// <summary> /// Process the filter on the specified image /// </summary> /// /// <param name="sourceData">Source image data</param> /// <param name="destinationData">Destination image data</param> /// protected override unsafe void ProcessFilter(BitmapData sourceData, BitmapData destinationData) { // get image dimension width = sourceData.Width; height = sourceData.Height; stride = destinationData.Stride; widthM1 = width - 1; heightM1 = height - 1; // allocate memory for source copy IntPtr sourceCopy = Win32.LocalAlloc(Win32.MemoryFlags.Fixed, destinationData.Stride * height); // check source image format if (sourceData.PixelFormat == PixelFormat.Format8bppIndexed) { // copy source image Win32.memcpy(sourceCopy, sourceData.Scan0, destinationData.Stride * height); } else { // convert color image to grayscale IFilter filter = new GrayscaleRMY( ); Bitmap grayImage = filter.Apply(sourceData); // copy the image BitmapData grayData = grayImage.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); Win32.memcpy(sourceCopy, grayData.Scan0, destinationData.Stride * height); grayImage.UnlockBits(grayData); // free the gray image grayImage.Dispose( ); } int offset = stride - width; int v, error; // do the job byte *src = (byte *)sourceCopy.ToPointer( ); byte *dst = (byte *)destinationData.Scan0.ToPointer( ); // for each line for (y = 0; y < height; y++) { // for each pixels for (x = 0; x < width; x++, src++, dst++) { v = *src; // fill the next destination pixel if (v < 128) { *dst = 0; error = v; } else { *dst = 255; error = v - 255; } // do error diffusion Diffuse(error, src); } src += offset; dst += offset; } // free memory for image copy Win32.LocalFree(sourceCopy); }
/// <summary> /// Process the filter on the specified image /// </summary> /// /// <param name="sourceData">Source image data</param> /// <param name="destinationData">Destination image data</param> /// protected override unsafe void ProcessFilter(BitmapData sourceData, BitmapData destinationData) { byte *src = null; byte *dst = (byte *)destinationData.Scan0.ToPointer( ); // get width and height int width = sourceData.Width; int height = sourceData.Height; int widthM1 = width - 1; int heightM1 = height - 1; int stride = destinationData.Stride; int offset = stride - width; // loop and array indexes int i, j, ir; // variables for gradient calculation double v, gx, gy, g, max = 0; // convert image to grayscale if it is color Bitmap grayImage = null; BitmapData grayData = null; if (sourceData.PixelFormat != PixelFormat.Format8bppIndexed) { // create grayscale filter IFilter filter = new GrayscaleRMY( ); // do the processing grayImage = filter.Apply(sourceData); // lock the image grayData = grayImage.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); // set source pointer src = (byte *)grayData.Scan0.ToPointer( ); } else { src = (byte *)sourceData.Scan0.ToPointer( ); } // do the processing job // skip one stride src += stride; dst += stride; // for each line for (int y = 1; y < heightM1; y++) { src++; dst++; // for each pixel for (int x = 1; x < widthM1; x++, src++, dst++) { gx = gy = 0; // for each kernel row for (i = 0; i < 3; i++) { ir = i - 1; // for each kernel column for (j = 0; j < 3; j++) { // source value v = src[ir * stride + j - 1]; gx += v * xKernel[i, j]; gy += v * yKernel[i, j]; } } // get gradient value // g = Math.Min( Math.Sqrt( gx * gx + gy * gy ), 255 ); g = Math.Min(Math.Abs(gx) + Math.Abs(gy), 255); // approximation if (g > max) { max = g; } *dst = (byte)g; } src += (offset + 1); dst += (offset + 1); } // do we need scaling if ((scaleIntensity) && (max != 255)) { // make the second pass for intensity scaling double factor = 255.0 / (double)max; dst = (byte *)destinationData.Scan0.ToPointer( ) + stride; // for each line for (int y = 1; y < heightM1; y++) { dst++; // for each pixel for (int x = 1; x < widthM1; x++, dst++) { *dst = (byte)(factor * *dst); } dst += (offset + 1); } } // release gray image, if there was conversion if (grayData != null) { grayImage.UnlockBits(grayData); grayImage.Dispose( ); } }