Friday, January 25, 2008

Unsharp Mask Algorithm in C#

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;
}


4 comments:

Ahmad said...

does not work.

pbsl said...

thanks for sharing this site. you can download lots of ebook from here


http://feboook.blogspot.com

Fredrik said...

I've made a version that uses only safe code (a bit slower, but will work on web hosts with medium trust).

Here's a tutorial on
how to implement an unsharp filter in C#

Nathan Wheeler said...

Your the first 17 lines are ok... then you get hit by ConvMatrix, which is undefined, unknown and the only reference I can pull from Google is some imageFS site docs... then there's the OBVIOUS need to RECOUNT YOUR FUCKING CURLY BRACES... there's literally like 5 more closing curly braces than there are OPENING curly braces, starting on line 51, where the method would be closed. line 56 starts a series of else if's without a beginning if...
oh... and the return types... WHAT THE FUCK ARE YOU RETURNING? "private unsafe Bitmap" implies that you're returning a Bitmap... line 12 -> return img; ... line 91 -> return true;... Are you just fucking stupid, or are you trying to muddy the waters and confuse people with this garbage?