Unsharp masking is a traditional darkroom technique that has proven very suitable for digital imaging.

Original

Unsharp Mask The principle of unsharp masking is to create a blurred copy of the image and compare it to the underlying original. The difference in colour values between the two images is greatest for the pixels near sharp edges. When this difference is subtracted from the original image, the edges will be accentuated.

private unsafe Bitmap UnsharpMask(Bitmap img, double amount, double radius, double threshold)

{

if (amount > 500) amount = 500;

amount = amount * 2;

if (radius > 50) radius = 50;

radius = radius * 2;

if (threshold > 255) threshold = 255;

if (radius == 0)

{

img.Dispose();

return img;

}

int w = img.Width; int h = img.Height;

Bitmap imgBlur = new Bitmap(w, h);

ConvMatrix con = new ConvMatrix();

imgBlur = (Bitmap)img.Clone();

BitmapFilter.Conv3x3(imgBlur, con);

BitmapData imgdata1 = img.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

BitmapData imgdata2 = imgBlur.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

byte* p1 = (byte*)(void*)imgdata1.Scan0;

byte* p2 = (byte*)(void*)imgdata2.Scan0;

if (threshold > 0)

{

for (int x = 0; x < y =" 0;" imgrvalue =" p1[2];" imggvalue =" p1[1];" imgbvalue =" p1[0];" imgblurrvalue =" p2[2];" imgblurgvalue =" p2[1];" imgblurbvalue =" p2[0];" rnew =" (Math.Abs(imgRValue">= (int)threshold)

? Math.Max(0, Math.Min(255, ((int)amount * (imgRValue - imgBlurRValue)) + imgRValue)) : imgRValue;

int gNew = (Math.Abs(imgGValue - imgBlurGValue) >= (int)threshold)

? Math.Max(0, Math.Min(255, ((int)amount * (imgGValue - imgBlurGValue)) + imgGValue)) : imgGValue;

int bNew = (Math.Abs(imgBValue - imgBlurBValue) >= (int)threshold)

? Math.Max(0, Math.Min(255, ((int)amount * (imgBValue - imgBlurBValue)) + imgBValue)) : imgBValue;

if ((imgRValue != rNew) || (imgGValue != gNew) || (imgBValue != bNew))

{

p1[0] = (byte)bNew;

p1[1] = (byte)gNew;

p1[2] = (byte)rNew;

//img.SetPixel(x, y, System.Drawing.Color.FromArgb(rNew, gNew, bNew));

}

p1 = p1 + 3;

p2 = p2 + 3;

}

}

}

else

{

for (int x = 0; x < y =" 0;" imgrvalue =" p1[2];" imggvalue =" p1[1];" imgbvalue =" p1[0];" imgblurrvalue =" p2[2];" imgblurgvalue =" p2[1];" imgblurbvalue =" p2[0];" rnew =" ((int)amount"> 255)

rNew = 255;

else if (rNew < rnew =" 0;" gnew =" ((int)amount"> 255)

gNew = 255;

else if (gNew < gnew =" 0;" bnew =" ((int)amount"> 255)

bNew = 255;

else if (bNew < bnew =" 0;" p1 =" p1" p2 =" p2" topleft =" 1," topmid =" 2," topright =" 1;" midleft =" 2," pixel =" 4," midright =" 2;" bottomleft =" 1," bottommid =" 2," bottomright =" 1;" factor =" 16;" offset =" 0;" topleft =" TopMid" topright =" MidLeft" pixel =" MidRight" bottomleft =" BottomMid" bottomright =" nVal;" 0 ="=" bsrc =" (Bitmap)b.Clone();" bmdata =" b.LockBits(new" bmsrc =" bSrc.LockBits(new" stride =" bmData.Stride;" stride2 =" stride" scan0 =" bmData.Scan0;" srcscan0 =" bmSrc.Scan0;" p =" (byte*)(void*)Scan0;" psrc =" (byte*)(void*)SrcScan0;" noffset =" stride" nwidth =" b.Width" nheight =" b.Height" y =" 0;" x =" 0;" npixel =" ((((pSrc[2]" npixel =" 0;"> 255) nPixel = 255;

p[5 + stride] = (byte)nPixel;

nPixel = ((((pSrc[1] * m.TopLeft) + (pSrc[4] * m.TopMid) + (pSrc[7] * m.TopRight) +

(pSrc[1 + stride] * m.MidLeft) + (pSrc[4 + stride] * m.Pixel) + (pSrc[7 + stride] * m.MidRight) +

(pSrc[1 + stride2] * m.BottomLeft) + (pSrc[4 + stride2] * m.BottomMid) + (pSrc[7 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);

if (nPixel < npixel =" 0;"> 255) nPixel = 255;

p[4 + stride] = (byte)nPixel;

nPixel = ((((pSrc[0] * m.TopLeft) + (pSrc[3] * m.TopMid) + (pSrc[6] * m.TopRight) +

(pSrc[0 + stride] * m.MidLeft) + (pSrc[3 + stride] * m.Pixel) + (pSrc[6 + stride] * m.MidRight) +

(pSrc[0 + stride2] * m.BottomLeft) + (pSrc[3 + stride2] * m.BottomMid) + (pSrc[6 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);

if (nPixel < npixel =" 0;"> 255) nPixel = 255;

p[3 + stride] = (byte)nPixel;

p += 3;

pSrc += 3;

}

p += nOffset;

pSrc += nOffset;

}

}

b.UnlockBits(bmData);

bSrc.UnlockBits(bmSrc);

return true;

}