A generic error occurred in GDI+ During a Bitmap Save - c#

When I run this code
Bitmap im = new Bitmap(600, 600, PixelFormat.Format16bppGrayScale);
int height = im.Height;
int width = im.Width;
Point p1 = new Point(0, 0);
Point p2 = new Point(im.Size.Width, 0);
Point p3 = new Point(im.Width / 2, im.Height);
Random r = new Random();
Point p = new Point(r.Next(0, im.Size.Width), r.Next(0, im.Size.Height));
BitmapData data = im.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format16bppGrayScale);
const int stride = 2;
int wsrtide = data.Stride;
unsafe
{
IntPtr osc0 = data.Scan0;
ushort* sc0 = (ushort*)data.Scan0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
*sc0 = 0;
sc0 += 1;
}
}
for (long i = 0; i < width * height; i++)
{
if (i % 1_000_000 == 0)
{
Console.WriteLine(i);
}
var ran = r.Next(0, 3);
Point tp;
switch (ran)
{
case 0:
tp = new Point((p1.X + p.X) / 2, (p1.Y + p.Y) / 2);
sc0 = (ushort*)((int)osc0 + (wsrtide * tp.Y + (tp.X * stride)));
*sc0 = ushort.MaxValue;
p = tp;
break;
case 1:
tp = new Point((p2.X + p.X) / 2, (p2.Y + p.Y) / 2);
sc0 = (ushort*)((int)osc0 + (wsrtide * tp.Y + (tp.X * stride)));
*sc0 = ushort.MaxValue;
p = tp;
break;
case 2:
tp = new Point((p3.X + p.X) / 2, (p3.Y + p.Y) / 2);
sc0 = (ushort*)((int)osc0 + (wsrtide * tp.Y + (tp.X * stride)));
*sc0 = ushort.MaxValue;
p = tp;
break;
}
}
im.UnlockBits(data);
im.Save(Environment.CurrentDirectory + "\\img.png");
im.Dispose();
It throws where I save the bitmap
System.Runtime.InteropServices.ExternalException: A generic error
occurred in GDI+.`
I am almost certain that this isn't caused by file permissions, when I give the program admin permission and delete the image to reset permissions it still throws. I can confirm that this code swapped with BitmapSetPixel() on RGB works.
My suspicion is that I'm messing up the pointers, but I'm not really sure. Also, curiously enough, it makes empty png files even though it throws.
The purpose of this code is to generate a Sierpinski triangle using the chaos game method.

Your problem is the Format16bppGrayScale i don't think the GDI supports it very well.
Basically if you just create the Bitmap in Format16bppGrayScale, and save it with nothing else, it still gives the error.
I have taken the liberty to rewrite your method Format32bppPArgb
private unsafe static void Main(string[] args)
{
var height = 600;
var width = 600;
var p1 = new Point(0, 0);
var p2 = new Point(width, 0);
var p3 = new Point(width / 2, height);
var r = new Random();
var p = new Point(r.Next(0, width), r.Next(0, width));
using (var im = new Bitmap(width, height, PixelFormat.Format32bppPArgb))
{
var data = im.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
var sc0 = (int*)data.Scan0;
var pLen = sc0 + height * width;
var black = Color.Black.ToArgb();
var white = Color.White.ToArgb();
for (var pI = sc0; pI < pLen; pI++)
*pI = black;
for (long i = 0; i < width * height; i++)
{
Point tp;
switch (r.Next(0, 3))
{
case 0:
tp = new Point((p1.X + p.X) / 2, (p1.Y + p.Y) / 2);
*(sc0 + tp.Y + tp.X * width) = white;
p = tp;
break;
case 1:
tp = new Point((p2.X + p.X) / 2, (p2.Y + p.Y) / 2);
*(sc0 + tp.Y + tp.X * width) = white;
p = tp;
break;
case 2:
tp = new Point((p3.X + p.X) / 2, (p3.Y + p.Y) / 2);
*(sc0 + tp.Y + tp.X * width) = white;
p = tp;
break;
}
}
im.UnlockBits(data);
im.Save(#"D:\img.png", ImageFormat.Png);
}
}
Result
You can convert it after the fact if you want, add pepper and salt to taste
Also if you get rid of all the points and cache the colors this will be a bit faster

Related

C# Search image .bmp inside a window if found then click x, y

I'm trying to find an image .bmp inside a window ( client ).. using c#
if someone could help me figure this out , it would be very nice ! :)
public List<Point> FindImageInImage(int parrentLeft, int parrentTop, int parrentRight, int parrentBottom, Bitmap searchingBitmap)
{
Bitmap bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics g = Graphics.FromImage(bmpScreenshot);
g.CopyFromScreen(parrentLeft, parrentTop, parrentRight, parrentBottom, Screen.PrimaryScreen.Bounds.Size);
var pixelFormatSize = Image.GetPixelFormatSize(bmpScreenshot.PixelFormat) / 8;
// Copy sourceBitmap to byte array
var sourceBitmapData = bmpScreenshot.LockBits(new Rectangle(0, 0, bmpScreenshot.Width, bmpScreenshot.Height),
ImageLockMode.ReadOnly, bmpScreenshot.PixelFormat);
var sourceBitmapBytesLength = sourceBitmapData.Stride * bmpScreenshot.Height;
var sourceBytes = new byte[sourceBitmapBytesLength];
Marshal.Copy(sourceBitmapData.Scan0, sourceBytes, 0, sourceBitmapBytesLength);
bmpScreenshot.UnlockBits(sourceBitmapData);
// Copy serchingBitmap to byte array
var serchingBitmapData =
searchingBitmap.LockBits(new Rectangle(0, 0, searchingBitmap.Width, searchingBitmap.Height),
ImageLockMode.ReadOnly, searchingBitmap.PixelFormat);
var serchingBitmapBytesLength = serchingBitmapData.Stride * searchingBitmap.Height;
var serchingBytes = new byte[serchingBitmapBytesLength];
Marshal.Copy(serchingBitmapData.Scan0, serchingBytes, 0, serchingBitmapBytesLength);
searchingBitmap.UnlockBits(serchingBitmapData);
var pointsList = new List<Point>();
// Serching entries
// minimazing serching zone
// sourceBitmap.Height - serchingBitmap.Height + 1
for (var mainY = 0; mainY < bmpScreenshot.Height - searchingBitmap.Height + 1; mainY++)
{
var sourceY = mainY * sourceBitmapData.Stride;
for (var mainX = 0; mainX < bmpScreenshot.Width - searchingBitmap.Width + 1; mainX++)
{// mainY & mainX - pixel coordinates of sourceBitmap
// sourceY + sourceX = pointer in array sourceBitmap bytes
var sourceX = mainX * pixelFormatSize;
var isEqual = true;
for (var c = 0; c < pixelFormatSize; c++)
{// through the bytes in pixel
if (sourceBytes[sourceX + sourceY + c] == serchingBytes[c])
continue;
isEqual = false;
break;
}
if (!isEqual) continue;
var isStop = false;
// find fist equalation and now we go deeper)
for (var secY = 0; secY < searchingBitmap.Height; secY++)
{
var serchY = secY * serchingBitmapData.Stride;
var sourceSecY = (mainY + secY) * sourceBitmapData.Stride;
for (var secX = 0; secX < searchingBitmap.Width; secX++)
{// secX & secY - coordinates of serchingBitmap
// serchX + serchY = pointer in array serchingBitmap bytes
var serchX = secX * pixelFormatSize;
var sourceSecX = (mainX + secX) * pixelFormatSize;
for (var c = 0; c < pixelFormatSize; c++)
{// through the bytes in pixel
if (sourceBytes[sourceSecX + sourceSecY + c] == serchingBytes[serchX + serchY + c]) continue;
// not equal - abort iteration
isStop = true;
break;
}
if (isStop) break;
}
if (isStop) break;
}
if (!isStop)
{// serching bitmap is founded!!
pointsList.Add(new Point(mainX, mainY));
}
}
}
bmpScreenshot.Dispose();
g.Dispose();
return pointsList;
}
private static Bitmap CaptureScreenRegion(Rectangle rect)
{
Bitmap BMP = new Bitmap(rect.Width, rect.Height, PixelFormat.Format24bppRgb);
Graphics GFX = System.Drawing.Graphics.FromImage(BMP);
GFX.CopyFromScreen(rect.X, rect.Y, 0, 0, rect.Size, CopyPixelOperation.SourceCopy);
return BMP;
}
There's what i'm trying to do.. i don't know if i do it correctly tho, because it doesnt seems to do anything..
i'm just trying to if (found) then mouseclick(x,y)
Bitmap Energybmp = (Bitmap)Bitmap.FromFile(#"C:\Users\Gabyy\Desktop\RS3Pixel\data\winrar.bmp");
//ss PaleWisp = PixelSearch(Rec, int.Parse(PaleColor, System.Globalization.NumberStyles.HexNumber), 5);
//Point EnergyRift = PixelSearch(MiniMap, int.Parse("4238C5", System.Globalization.NumberStyles.HexNumber), 5);
List<Point> Energy = FindImageInImage(0, 0, 1920, 1080, Energybmp);
if (Energy.Count >= 1)
AutoItX.MouseClick("left", Energy[1].X, Energy[1].Y, 1, -1);

How do I find a image on the screen and get the mouse coordinates?

I want to find the image on the screen and get the x,y coordinates if it matched on the screen. I already know how to move the mouse and click using this x,y coordinates.
EG:
I want to give icon image and the code will get a screenshot of desktop and find the image, move mouse.
The following code works, but if I change the resolution of the screen I have to get the image (bmpMatch) again.
private static Rectangle FindImageOnScreen(Bitmap bmpMatch, bool ExactMatch)
{
Rectangle rct = Rectangle.Empty;
try
{
Bitmap ScreenBmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics g = Graphics.FromImage(ScreenBmp);
g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0, 0,
ScreenBmp.Size,
CopyPixelOperation.SourceCopy);
BitmapData ImgBmd = bmpMatch.LockBits(new Rectangle(0, 0, bmpMatch.Width, bmpMatch.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData ScreenBmd = ScreenBmp.LockBits(new Rectangle(0, 0, ScreenBmp.Width, ScreenBmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
byte[] ImgByts = new byte[(Math.Abs(ImgBmd.Stride) * bmpMatch.Height) - 1 + 1];
byte[] ScreenByts = new byte[(Math.Abs(ScreenBmd.Stride) * ScreenBmp.Height) - 1 + 1];
Marshal.Copy(ImgBmd.Scan0, ImgByts, 0, ImgByts.Length);
Marshal.Copy(ScreenBmd.Scan0, ScreenByts, 0, ScreenByts.Length);
bool FoundMatch = false;
int sindx, iindx;
int spc, ipc;
int skpx = System.Convert.ToInt32((bmpMatch.Width - 1) / (double)10);
if (skpx < 1 | ExactMatch)
skpx = 1;
int skpy = System.Convert.ToInt32((bmpMatch.Height - 1) / (double)10);
if (skpy < 1 | ExactMatch)
skpy = 1;
for (int si = 0; si <= ScreenByts.Length - 1; si += 3)
{
FoundMatch = true;
for (int iy = 0; iy <= ImgBmd.Height - 1; iy += skpy)
{
for (int ix = 0; ix <= ImgBmd.Width - 1; ix += skpx)
{
sindx = (iy * ScreenBmd.Stride) + (ix * 3) + si;
iindx = (iy * ImgBmd.Stride) + (ix * 3);
spc = Color.FromArgb(ScreenByts[sindx + 2], ScreenByts[sindx + 1], ScreenByts[sindx]).ToArgb();
ipc = Color.FromArgb(ImgByts[iindx + 2], ImgByts[iindx + 1], ImgByts[iindx]).ToArgb();
if (spc != ipc)
{
FoundMatch = false;
iy = ImgBmd.Height - 1;
ix = ImgBmd.Width - 1;
}
}
}
if (FoundMatch)
{
double r = si / (double)(ScreenBmp.Width * 3);
double c = ScreenBmp.Width * (r % 1);
if (r % 1 >= 0.5)
r -= 1;
rct.X = System.Convert.ToInt32(c);
rct.Y = System.Convert.ToInt32(r);
rct.Width = bmpMatch.Width;
rct.Height = bmpMatch.Height;
break;
}
}
bmpMatch.UnlockBits(ImgBmd);
ScreenBmp.UnlockBits(ScreenBmd);
//ScreenBmp.Dispose();
return rct;
} catch(Exception ex)
{
Console.Write(ex.Message);
}
return rct;
}
is there anyway I can give any size of image, and get it search from the desktop screenshot.
I was looking for exactly this, thank you very much! Regarding your question, although I don't understand the code well, it worked for me to change the increment in the for, instead of incrementing from 3 to 3, I put it from 1 to 1, it worked for me to find the coordinates in different resolution with the same image
private static Rectangle FindImageOnScreen(Bitmap bmpMatch, bool ExactMatch)
{
Rectangle rct = Rectangle.Empty;
try
{
Bitmap ScreenBmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics g = Graphics.FromImage(ScreenBmp);
g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0, 0,
ScreenBmp.Size,
CopyPixelOperation.SourceCopy);
BitmapData ImgBmd = bmpMatch.LockBits(new Rectangle(0, 0, bmpMatch.Width, bmpMatch.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData ScreenBmd = ScreenBmp.LockBits(new Rectangle(0, 0, ScreenBmp.Width, ScreenBmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
byte[] ImgByts = new byte[(Math.Abs(ImgBmd.Stride) * bmpMatch.Height) - 1 + 1];
byte[] ScreenByts = new byte[(Math.Abs(ScreenBmd.Stride) * ScreenBmp.Height) - 1 + 1];
Marshal.Copy(ImgBmd.Scan0, ImgByts, 0, ImgByts.Length);
Marshal.Copy(ScreenBmd.Scan0, ScreenByts, 0, ScreenByts.Length);
bool FoundMatch = false;
int sindx, iindx;
int spc, ipc;
int skpx = System.Convert.ToInt32((bmpMatch.Width - 1) / (double)10);
if (skpx < 1 | ExactMatch)
skpx = 1;
int skpy = System.Convert.ToInt32((bmpMatch.Height - 1) / (double)10);
if (skpy < 1 | ExactMatch)
skpy = 1;
for (int si = 0; si <= ScreenByts.Length - 1; si ++) //here modify
{
FoundMatch = true;
for (int iy = 0; iy <= ImgBmd.Height - 1; iy += skpy)
{
for (int ix = 0; ix <= ImgBmd.Width - 1; ix += skpx)
{
sindx = (iy * ScreenBmd.Stride) + (ix * 3) + si;
iindx = (iy * ImgBmd.Stride) + (ix * 3);
spc = Color.FromArgb(ScreenByts[sindx + 2], ScreenByts[sindx + 1], ScreenByts[sindx]).ToArgb();
ipc = Color.FromArgb(ImgByts[iindx + 2], ImgByts[iindx + 1], ImgByts[iindx]).ToArgb();
if (spc != ipc)
{
FoundMatch = false;
iy = ImgBmd.Height - 1;
ix = ImgBmd.Width - 1;
}
}
}
if (FoundMatch)
{
double r = si / (double)(ScreenBmp.Width * 3);
double c = ScreenBmp.Width * (r % 1);
if (r % 1 >= 0.5)
r -= 1;
rct.X = System.Convert.ToInt32(c);
rct.Y = System.Convert.ToInt32(r);
rct.Width = bmpMatch.Width;
rct.Height = bmpMatch.Height;
break;
}
}
bmpMatch.UnlockBits(ImgBmd);
ScreenBmp.UnlockBits(ScreenBmd);
//ScreenBmp.Dispose();
return rct;
} catch(Exception ex)
{
Console.Write(ex.Message);
}
return rct;
}

Index out of bounds when calculating pixel index

I have my image cropping app based on:
http://www.c-sharpcorner.com/UploadFile/55275a/windowsphone-image-crop-with-rectangle/
I modified it a little bit so I can resize rectangle instead of creating new
so my whole method look like:
private async void Accept_Click(object sender, EventArgs e)
{
WriteableBitmap wb = new WriteableBitmap(image);
double originalImageWidth = wb.PixelWidth;
double originalImageHeight = wb.PixelHeight;
double displayedWidth = image1.ActualWidth;
double displayedHeight = image1.ActualHeight;
double widthRatio = originalImageWidth / displayedWidth;
double heightRatio = originalImageHeight / displayedHeight;
r = (Rectangle) (from c in LayoutRoot.Children
where c.Opacity == .5 select c).First();
GeneralTransform gt = r.TransformToVisual(LayoutRoot);
Point p = gt.Transform(new Point(0, 0));
Point1 = (r.TransformToVisual(this)).Transform(new Point(0, 0));
Point2 = new Point(Point1.X + r.Width, Point1.Y + r.Height);
WriteableBitmap newImage = new WriteableBitmap(
(int) (widthRatio * Math.Abs(Point2.X - Point1.X)),
(int) (heightRatio * Math.Abs(Point2.Y - Point1.Y)));
int xoffset = (int) (((Point1.X < Point2.X) ? Point1.X : Point2.X) * widthRatio);
int yoffset = (int) (((Point1.Y < Point2.Y) ? Point1.Y : Point2.X) * heightRatio);
if (newImage.Pixels.Length > 0)
{
for (int i = 0; i < newImage.Pixels.Length; i++)
{
int x = (int) ((i % newImage.PixelWidth) + xoffset);
int y = (int) ((i / newImage.PixelWidth) + yoffset);
newImage.Pixels[i] = wb.Pixels[y * wb.PixelWidth + x];
}
using (MemoryStream ms = new MemoryStream())
{
newImage.SaveJpeg(ms, (int) newImage.PixelWidth,
(int) newImage.PixelHeight, 0, 100);
image.SetSource(ms);
}
}
else
{
}
ProgressBar pb = new ProgressBar();
pb.IsEnabled = true;
LayoutRoot.Children.Add(pb);
int idReceipt = (int) PhoneApplicationService.Current.State["paragon"];
await ReceiptsHelper.addPhotosToReceipt(image, idReceipt);
NavigationService.Navigate(new Uri("/7.0/StronaParagonu.xaml", UriKind.Relative));
}
When my image is vertical everything works fine, but when my image is horizontal I get Array Index Out Of Bounds Exception at:
newImage.Pixels[i] = wb.Pixels[y * wb.PixelWidth + x];
I don't know exactly what am I doing wrong.
Anybody can help?
EDIT:
I changed my code to:
if (wb.PixelWidth > wb.PixelHeight)
{
for (int i = 0; i < newImage.Pixels.Length; i++)
{
int x = (int)((i % newImage.PixelWidth) + xoffset);
int y = (int)((i / newImage.PixelWidth) + yoffset);
newImage.Pixels[i] = wb.Pixels[x * wb.PixelHeight + y];
}
}
else
{
for (int i = 0; i < newImage.Pixels.Length; i++)
{
int x = (int)((i % newImage.PixelWidth) + xoffset);
int y = (int)((i / newImage.PixelWidth) + yoffset);
newImage.Pixels[i] = wb.Pixels[y * wb.PixelWidth + x];
}
}
In result I've got something like this
Maybe there is some workaround in which I can flip image 90 degree?
I tried WriteableBitmapEx but it doesnt work.
First thing I see is:
int yoffset = (int) (((Point1.Y < Point2.Y) ? Point1.Y : Point2.X) * heightRatio);
I guess there should be Point2.Y?
Second thing is what #Rashed mentioned in comment:
When you want get horizontal image, you must change X and Y place: newImage.Pixels[i] = wb.Pixels[x * wb.PixelHeight + y];
But please take a note I'm really guessing here since it's late and I don't see sharp ;-)

How to increase Gaussian Blur strength in Windows Form

I found some great code here on SO and have implemented it in my app and although it is "working", the blur effect is not strong enough to actually realise (without focusing very hard on it) that it has actually blurred anything.
The code is (quite long, sorry):
Bitmap screenshot = null;
void BlurForm()
{
/*
The best time (I assume) is to change the blur when the user as left the window,
as opposed to doing it when they want to open the window, since this may be a
little intensive.
*/
screenshot = null;
blurred.Image = null; // This variable is the PictureBox that's on the Form
screenshot = Screenshot.TakeSnapshot(this);
BitmapFilter.GaussianBlur(screenshot, 4);
blurred.Image = screenshot;
blurred.SendToBack();
}
public class ConvMatrix
{
public int TopLeft = 0, TopMid = 0, TopRight = 0;
public int MidLeft = 0, Pixel = 1, MidRight = 0;
public int BottomLeft = 0, BottomMid = 0, BottomRight = 0;
public int Factor = 1;
public int Offset = 0;
public void SetAll(int nVal)
{
TopLeft = TopMid = TopRight = MidLeft = Pixel = MidRight = BottomLeft = BottomMid = BottomRight = nVal;
}
}
public class BitmapFilter
{
private static bool Conv3x3(Bitmap b, ConvMatrix m)
{
// Avoid divide by zero errors
if (0 == m.Factor) return false;
Bitmap bSrc = (Bitmap)b.Clone();
// GDI+ still lies to us - the return format is BGR, NOT RGB.
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
int stride2 = stride * 2;
System.IntPtr Scan0 = bmData.Scan0;
System.IntPtr SrcScan0 = bmSrc.Scan0;
unsafe
{
byte* p = (byte*)(void*)Scan0;
byte* pSrc = (byte*)(void*)SrcScan0;
int nOffset = stride + 6 - b.Width * 3;
int nWidth = b.Width - 2;
int nHeight = b.Height - 2;
int nPixel;
for (int y = 0; y < nHeight; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
nPixel = ((((pSrc[2] * m.TopLeft) + (pSrc[5] * m.TopMid) + (pSrc[8] * m.TopRight) +
(pSrc[2 + stride] * m.MidLeft) + (pSrc[5 + stride] * m.Pixel) + (pSrc[8 + stride] * m.MidRight) +
(pSrc[2 + stride2] * m.BottomLeft) + (pSrc[5 + stride2] * m.BottomMid) + (pSrc[8 + stride2] * m.BottomRight)) / m.Factor) + m.Offset);
if (nPixel < 0) nPixel = 0;
if (nPixel > 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 < 0) nPixel = 0;
if (nPixel > 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 < 0) nPixel = 0;
if (nPixel > 255) nPixel = 255;
p[3 + stride] = (byte)nPixel;
p += 3;
pSrc += 3;
}
p += nOffset;
pSrc += nOffset;
}
}
b.UnlockBits(bmData);
bSrc.UnlockBits(bmSrc);
return true;
}
public static bool GaussianBlur(Bitmap b, int nWeight /* default to 4*/)
{
ConvMatrix m = new ConvMatrix();
m.SetAll(1);
m.Pixel = nWeight;
m.TopMid = m.MidLeft = m.MidRight = m.BottomMid = 2;
m.Factor = nWeight + 12;
return BitmapFilter.Conv3x3(b, m);
}
}
class Screenshot
{
public static Bitmap TakeSnapshot(Control ctl)
{
Bitmap bmp = new Bitmap(ctl.Size.Width, ctl.Size.Height);
using (Graphics g = System.Drawing.Graphics.FromImage(bmp))
{
g.CopyFromScreen(
ctl.PointToScreen(ctl.ClientRectangle.Location),
new Point(0, 0), ctl.ClientRectangle.Size
);
}
return bmp;
}
}
I've tried changing every single value in there and it doesn't matter which value(s) I change, I just can't get it to have a stronger blur effect. How can I increase the strength of the Gaussian Blur?
The Form is 80% Opaque, so the blur effect you would see is the windows wallpaper or whatever is behind the form - but blurred. Only problem (as I've said) is that the blur is not strong at all.
After just glancing at the code, it looks to me like the blur filter is hardcoded to only operate in a 3x3 area at a time, severely restricting how blurred it can make an image.
Unless I'm mistaken, the only way to significantly increase the amount of blurring is to find a more sophisticated implementation.

Why does this bitmap-manipulation code subtract the width from the stride?

What does the line imagePointer1 += bitmapData1.Stride - (bitmapData1.Width * 4); mean in the following code?
var width = bitmap.Width;
var height = bitmap.Width;
var horizontalProjection = new double[width];
var verticalProjection = new double[height];
var bitmapData1 = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
unsafe
{
var imagePointer1 = (byte*)bitmapData1.Scan0;
for (var y = 0; y < height; y++)
{
for (var x = 0; x < width; x++)
{
var blu = imagePointer1[0];
var green = imagePointer1[1];
var red = imagePointer1[2];
int luminosity = (byte)(((0.2126 * red) + (0.7152 * green)) + (0.0722 * blu));
horizontalProjection[x] += luminosity;
verticalProjection[y] += luminosity;
imagePointer1 += 4;
}
imagePointer1 += bitmapData1.Stride - (bitmapData1.Width * 4);
}
}
MaximizeScale(ref horizontalProjection, height);
MaximizeScale(ref verticalProjection, width);
var projections =
new[]
{
horizontalProjection,
verticalProjection
};
bitmap.UnlockBits(bitmapData1);
return projections;
The code is simply incrementing the pointer contained in the variable imagePointer1.
The reason you have to increment by the stride - (width * 4) is because of the way bitmaps are represented in memory.
There's a very comprehensive explanation available as part of Bob Powell's GDI+ FAQ.

Categories

Resources