all groups > dotnet performance > january 2004 >
Hi, I'm having some problems getting the required speed for a small app i'm currently writting. I rewrote the getPixel() fucntion that i thought was my orginal bottle neck, but i'm still taking 5-6 minutes to calcualte the score of around 6000 points. Does anyone have any suggestions as to other problems that may be slowing down this function?? private int returnArgb(GraphicsPath linePath, Bitmap Bmp) { int Argb; int score = 0; int RGBLightBlue = (Color.LightBlue.R<<16)+(Color.LightBlue.G<<8)+(Color.LightBlue.B); int RGBWhite = (Color.White.R<<16)+(Color.White.G<<8)+(Color.White.B); int RGBRed = (Color.Red.R<<16)+(Color.Red.G<<8)+(Color.Red.B); int RGBDarkGreen = (Color.DarkSeaGreen.R<<16)+(Color.DarkSeaGreen.G<<8)+(Color.DarkSeaGreen.B); paint.progressBar1.Maximum = linePath.PointCount; paint.statusBar1.Text = "Color Detection"; BitmapData bmData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; unsafe { int PixelSize = 3; byte blue, green, red; for(int i = 0; i<linePath.PointCount; i++) { paint.progressBar1.PerformStep(); int y = Convert.ToInt16(linePath.PathPoints[i].X); int x = Convert.ToInt16(linePath.PathPoints[i].Y); byte* row=(byte *)bmData.Scan0+(x*bmData.Stride); blue = row[(y*PixelSize)]; green = row[(y*PixelSize)+1]; red = row[(y*PixelSize)+2]; Argb = (red<<16)+(green<<8)+(blue); if(Argb == RGBLightBlue) continue; else if(Argb == RGBRed) { score = score+2; } else if(Argb == RGBWhite) { score = score+2; } else if(Argb == RGBDarkGreen) { score = score+4; } else score++; } } Bmp.UnlockBits(bmData); return score; } Regards
A couple suggestions and a question... First and most important, don't update the progress bar with every iteration. GDI+ calls are very expensive performance wise. Try to determine an appropriate interval to update the progress bar. Using a power of 10 for your interval is usually ok (10, 1000, 10000), but experiment with it to determine the best interval. Next, try using a switch statement as opposed to 'if/if else/if else'. There is another thread in this newsgroup that indicates switch produces more efficient IL. Third, I don't know if this will help performance or not, but the IL is a little different (uses the dup opcode instead of ldarg a second time), but you could use 'score+=2' instead of 'score=score+2'. I'm guessing the dup opcode is more efficient due to already having the value on the stack and just copying that value instead of having to process the value from the variable a second time, but I don't know how much better Fourth, instead of having the system calculate 'y*PixelSize' three times, calculate it once and cache the value. int y = Convert.ToInt16(linePath.PathPoints[i].X); becomes int y = (Convert.ToInt16(linePath.PathPoints[i].X))*PixelSize; Fifth, if you expect the values from PathPoints to all be integers, don't use the 'Convert' class functions. The class calls into mscorlib to do the conversion, and that incurs more overhead. Change the line to int y = ((short)(linePath.PathPoints[i].X))*PixelSize; Now, the opcode conv.i4 is used. This is much faster than a call into another assembly (add method to stack, etc...) Question: Is there a reason you are converting the floating point value from 'linePath.PathPoints[i].X(Y)' to a 16 bit integer as opposed to a 32 bit integer? The variables you are using for the values are 32 bit. Without looking at the IL produced, this would seem to force a conversion from float(single) to a 16 bit integer, then it has to be cast to a 32 bit integer for storage in the variable. If you don't need to do the conversion to a 16 bit integer (short) then the line int y = ((short)(linePath.PathPoints[i].X))*PixelSize; changes to int y = ((int)(linePath.PathPoints[i].X))*PixelSize; Hope this helps. There are probably other minor optimizations, but these are the ones I can see being helpful, especially the interval for the progress bar update. Ray [quoted text, click to view] "Sam Davies" <sam@samdavies.co.uk> wrote in message news:5600106.0401260458.715b748b@posting.google.com... > Hi, > > I'm having some problems getting the required speed for a small app > i'm currently writting. I rewrote the getPixel() fucntion that i > thought was my orginal bottle neck, but i'm still taking 5-6 minutes > to calcualte the score of around 6000 points. Does anyone have any > suggestions as to other problems that may be slowing down this > function?? > > > private int returnArgb(GraphicsPath linePath, Bitmap Bmp) > { > int Argb; > int score = 0; > int RGBLightBlue = (Color.LightBlue.R<<16)+(Color.LightBlue.G<<8)+(Color.LightBlue.B); > int RGBWhite = (Color.White.R<<16)+(Color.White.G<<8)+(Color.White.B); > int RGBRed = (Color.Red.R<<16)+(Color.Red.G<<8)+(Color.Red.B); > int RGBDarkGreen = (Color.DarkSeaGreen.R<<16)+(Color.DarkSeaGreen.G<<8)+(Color.DarkSeaGreen.B); > > paint.progressBar1.Maximum = linePath.PointCount; > paint.statusBar1.Text = "Color Detection"; > > BitmapData bmData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, > Bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); > int stride = bmData.Stride; > System.IntPtr Scan0 = bmData.Scan0; > > unsafe > { > int PixelSize = 3; > byte blue, green, red; > for(int i = 0; i<linePath.PointCount; i++) > { > paint.progressBar1.PerformStep(); > int y = Convert.ToInt16(linePath.PathPoints[i].X); > int x = Convert.ToInt16(linePath.PathPoints[i].Y); > > byte* row=(byte *)bmData.Scan0+(x*bmData.Stride); > blue = row[(y*PixelSize)]; > green = row[(y*PixelSize)+1]; > red = row[(y*PixelSize)+2]; > > Argb = (red<<16)+(green<<8)+(blue); > > > if(Argb == RGBLightBlue) > continue; > else if(Argb == RGBRed) > { > score = score+2; > } > else if(Argb == RGBWhite) > { > score = score+2; > } > else if(Argb == RGBDarkGreen) > { > score = score+4; > } > else > score++; > } > } > > Bmp.UnlockBits(bmData); > > return score; > } > > > > Regards > Sam
Hey Ray, Thnaks for the help, was exactly what i was looking for. I'm afraid the int conversion stuff you picked up on just highlighted my limited programming experience. I made all the changes you suggested but although i have a slight improvment in speed, it still taking a couple of minutes to run though my graphics path I read somewhere on another thread that the graphics path is a particuarly slow way to access data and that i might be adviced to use something quicker. I could if needed not write to a graphics path in the first place and instead use an array or something similar. Do you have any ideas? Regards Sam [quoted text, click to view] "Ray Beckett" <raybeckett@hotmail.com> wrote in message news:<eJZlvAE5DHA.2496@TK2MSFTNGP09.phx.gbl>... > A couple suggestions and a question... > > First and most important, don't update the progress bar with every > iteration. GDI+ calls are very expensive performance wise. Try to > determine an appropriate interval to update the progress bar. Using a power > of 10 for your interval is usually ok (10, 1000, 10000), but experiment with > it to determine the best interval. > > Next, try using a switch statement as opposed to 'if/if else/if else'. > There is another thread in this newsgroup that indicates switch produces > more efficient IL. > > Third, I don't know if this will help performance or not, but the IL is a > little different (uses the dup opcode instead of ldarg a second time), but > you could use 'score+=2' instead of 'score=score+2'. I'm guessing the dup > opcode is more efficient due to already having the value on the stack and > just copying that value instead of having to process the value from the > variable a second time, but I don't know how much better > > Fourth, instead of having the system calculate 'y*PixelSize' three times, > calculate it once and cache the value. > int y = Convert.ToInt16(linePath.PathPoints[i].X); > becomes > int y = (Convert.ToInt16(linePath.PathPoints[i].X))*PixelSize; > > Fifth, if you expect the values from PathPoints to all be integers, don't > use the 'Convert' class functions. The class calls into mscorlib to do the > conversion, and that incurs more overhead. Change the line to > int y = ((short)(linePath.PathPoints[i].X))*PixelSize; > Now, the opcode conv.i4 is used. This is much faster than a call into > another assembly (add method to stack, etc...) > > > > > Question: Is there a reason you are converting the floating point value > from 'linePath.PathPoints[i].X(Y)' to a 16 bit integer as opposed to a 32 > bit integer? The variables you are using for the values are 32 bit. > Without looking at the IL produced, this would seem to force a conversion > from float(single) to a 16 bit integer, then it has to be cast to a 32 bit > integer for storage in the variable. > If you don't need to do the conversion to a 16 bit integer (short) then the > line > int y = ((short)(linePath.PathPoints[i].X))*PixelSize; > changes to > int y = ((int)(linePath.PathPoints[i].X))*PixelSize; > > Hope this helps. There are probably other minor optimizations, but these > are the ones I can see being helpful, especially the interval for the > progress bar update. > > Ray > > "Sam Davies" <sam@samdavies.co.uk> wrote in message > news:5600106.0401260458.715b748b@posting.google.com... > > Hi, > > > > I'm having some problems getting the required speed for a small app > > i'm currently writting. I rewrote the getPixel() fucntion that i > > thought was my orginal bottle neck, but i'm still taking 5-6 minutes > > to calcualte the score of around 6000 points. Does anyone have any > > suggestions as to other problems that may be slowing down this > > function?? > > > > > > private int returnArgb(GraphicsPath linePath, Bitmap Bmp) > > { > > int Argb; > > int score = 0; > > int RGBLightBlue = > (Color.LightBlue.R<<16)+(Color.LightBlue.G<<8)+(Color.LightBlue.B); > > int RGBWhite = (Color.White.R<<16)+(Color.White.G<<8)+(Color.White.B); > > int RGBRed = (Color.Red.R<<16)+(Color.Red.G<<8)+(Color.Red.B); > > int RGBDarkGreen = > (Color.DarkSeaGreen.R<<16)+(Color.DarkSeaGreen.G<<8)+(Color.DarkSeaGreen.B); > > > > paint.progressBar1.Maximum = linePath.PointCount; > > paint.statusBar1.Text = "Color Detection"; > > > > BitmapData bmData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, > > Bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); > > int stride = bmData.Stride; > > System.IntPtr Scan0 = bmData.Scan0; > > > > unsafe > > { > > int PixelSize = 3; > > byte blue, green, red; > > for(int i = 0; i<linePath.PointCount; i++) > > { > > paint.progressBar1.PerformStep(); > > int y = Convert.ToInt16(linePath.PathPoints[i].X); > > int x = Convert.ToInt16(linePath.PathPoints[i].Y); > > > > byte* row=(byte *)bmData.Scan0+(x*bmData.Stride); > > blue = row[(y*PixelSize)]; > > green = row[(y*PixelSize)+1]; > > red = row[(y*PixelSize)+2]; > > > > Argb = (red<<16)+(green<<8)+(blue); > > > > > > if(Argb == RGBLightBlue) > > continue; > > else if(Argb == RGBRed) > > { > > score = score+2; > > } > > else if(Argb == RGBWhite) > > { > > score = score+2; > > } > > else if(Argb == RGBDarkGreen) > > { > > score = score+4; > > } > > else > > score++; > > } > > } > > > > Bmp.UnlockBits(bmData); > > > > return score; > > } > > > > > > > > Regards
This may be "way out there" but at the expense of memory, could you use the format Format32bppRgb? Then, you could pick up the data using one array access to grab all 4 bytes (use an array of Ints) and eliminate all the shifting as now you could just compare the Int you read with your precalculated Ints for the colours. I believe the format is R,G,B,nothing so you'd have to shift your precalculated colour Ints further to the left. This is way I did this sort of thing in Assembler for the 68000 many years ago! Also, are you running this in Visual Studio because I believe all the optimizations are turned OFF if you are! Really you need to profile this and find out where the bottleneck is. Even just outputing the current time before you do your graphics path things, and before and after this routine will show you where to start. Does this help? Tom [quoted text, click to view] "Sam Davies" <sam@samdavies.co.uk> wrote in message news:5600106.0401270331.6ffab763@posting.google.com... > Hey Ray, > > Thnaks for the help, was exactly what i was looking for. I'm afraid > the int conversion stuff you picked up on just highlighted my limited > programming experience. I made all the changes you suggested but > although i have a slight improvment in speed, it still taking a couple > of minutes to run though my graphics path > > I read somewhere on another thread that the graphics path is a > particuarly slow way to access data and that i might be adviced to use > something quicker. I could if needed not write to a graphics path in > the first place and instead use an array or something similar. Do you > have any ideas? > > Regards > Sam > > "Ray Beckett" <raybeckett@hotmail.com> wrote in message news:<eJZlvAE5DHA.2496@TK2MSFTNGP09.phx.gbl>... > > A couple suggestions and a question... > > > > First and most important, don't update the progress bar with every > > iteration. GDI+ calls are very expensive performance wise. Try to > > determine an appropriate interval to update the progress bar. Using a p ower > > of 10 for your interval is usually ok (10, 1000, 10000), but experiment with > > it to determine the best interval. > > > > Next, try using a switch statement as opposed to 'if/if else/if else'. > > There is another thread in this newsgroup that indicates switch produces > > more efficient IL. > > > > Third, I don't know if this will help performance or not, but the IL is a > > little different (uses the dup opcode instead of ldarg a second time), but > > you could use 'score+=2' instead of 'score=score+2'. I'm guessing the dup > > opcode is more efficient due to already having the value on the stack and > > just copying that value instead of having to process the value from the > > variable a second time, but I don't know how much better > > > > Fourth, instead of having the system calculate 'y*PixelSize' three times, > > calculate it once and cache the value. > > int y = Convert.ToInt16(linePath.PathPoints[i].X); > > becomes > > int y = (Convert.ToInt16(linePath.PathPoints[i].X))*PixelSize; > > > > Fifth, if you expect the values from PathPoints to all be integers, don't > > use the 'Convert' class functions. The class calls into mscorlib to do the > > conversion, and that incurs more overhead. Change the line to > > int y = ((short)(linePath.PathPoints[i].X))*PixelSize; > > Now, the opcode conv.i4 is used. This is much faster than a call into > > another assembly (add method to stack, etc...) > > > > > > > > > > Question: Is there a reason you are converting the floating point value > > from 'linePath.PathPoints[i].X(Y)' to a 16 bit integer as opposed to a 32 > > bit integer? The variables you are using for the values are 32 bit. > > Without looking at the IL produced, this would seem to force a conversion > > from float(single) to a 16 bit integer, then it has to be cast to a 32 bit > > integer for storage in the variable. > > If you don't need to do the conversion to a 16 bit integer (short) then the > > line > > int y = ((short)(linePath.PathPoints[i].X))*PixelSize; > > changes to > > int y = ((int)(linePath.PathPoints[i].X))*PixelSize; > > > > Hope this helps. There are probably other minor optimizations, but these > > are the ones I can see being helpful, especially the interval for the > > progress bar update. > > > > Ray > > > > "Sam Davies" <sam@samdavies.co.uk> wrote in message > > news:5600106.0401260458.715b748b@posting.google.com... > > > Hi, > > > > > > I'm having some problems getting the required speed for a small app > > > i'm currently writting. I rewrote the getPixel() fucntion that i > > > thought was my orginal bottle neck, but i'm still taking 5-6 minutes > > > to calcualte the score of around 6000 points. Does anyone have any > > > suggestions as to other problems that may be slowing down this > > > function?? > > > > > > > > > private int returnArgb(GraphicsPath linePath, Bitmap Bmp) > > > { > > > int Argb; > > > int score = 0; > > > int RGBLightBlue = > > (Color.LightBlue.R<<16)+(Color.LightBlue.G<<8)+(Color.LightBlue.B); > > > int RGBWhite = (Color.White.R<<16)+(Color.White.G<<8)+(Color.White.B); > > > int RGBRed = (Color.Red.R<<16)+(Color.Red.G<<8)+(Color.Red.B); > > > int RGBDarkGreen = > > (Color.DarkSeaGreen.R<<16)+(Color.DarkSeaGreen.G<<8)+(Color.DarkSeaGreen.B); > > > > > > paint.progressBar1.Maximum = linePath.PointCount; > > > paint.statusBar1.Text = "Color Detection"; > > > > > > BitmapData bmData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, > > > Bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); > > > int stride = bmData.Stride; > > > System.IntPtr Scan0 = bmData.Scan0; > > > > > > unsafe > > > { > > > int PixelSize = 3; > > > byte blue, green, red; > > > for(int i = 0; i<linePath.PointCount; i++) > > > { > > > paint.progressBar1.PerformStep(); > > > int y = Convert.ToInt16(linePath.PathPoints[i].X); > > > int x = Convert.ToInt16(linePath.PathPoints[i].Y); > > > > > > byte* row=(byte *)bmData.Scan0+(x*bmData.Stride); > > > blue = row[(y*PixelSize)]; > > > green = row[(y*PixelSize)+1]; > > > red = row[(y*PixelSize)+2]; > > > > > > Argb = (red<<16)+(green<<8)+(blue); > > > > > > > > > if(Argb == RGBLightBlue) > > > continue; > > > else if(Argb == RGBRed) > > > { > > > score = score+2; > > > } > > > else if(Argb == RGBWhite) > > > { > > > score = score+2; > > > } > > > else if(Argb == RGBDarkGreen) > > > { > > > score = score+4; > > > } > > > else > > > score++; > > > } > > > } > > > > > > Bmp.UnlockBits(bmData); > > > > > > return score; > > > } > > > > > > > > > > > > Regards > > > Sam
Good points, [quoted text, click to view] > Third, I don't know if this will help performance or not, but the IL is a > little different (uses the dup opcode instead of ldarg a second time), but > you could use 'score+=2' instead of 'score=score+2'. I'm guessing the dup > opcode is more efficient due to already having the value on the stack and > just copying that value instead of having to process the value from the > variable a second time, but I don't know how much better
I wouldn't worry exceedingly about slightly different IL. In some cases, this will result the exact same JIT output. Other suggestions look pretty good :). -mike MVP [quoted text, click to view] > Fourth, instead of having the system calculate 'y*PixelSize' three times, > calculate it once and cache the value. > int y = Convert.ToInt16(linePath.PathPoints[i].X); > becomes > int y = (Convert.ToInt16(linePath.PathPoints[i].X))*PixelSize; > > Fifth, if you expect the values from PathPoints to all be integers, don't > use the 'Convert' class functions. The class calls into mscorlib to do the > conversion, and that incurs more overhead. Change the line to > int y = ((short)(linePath.PathPoints[i].X))*PixelSize; > Now, the opcode conv.i4 is used. This is much faster than a call into > another assembly (add method to stack, etc...) > > > > > Question: Is there a reason you are converting the floating point value > from 'linePath.PathPoints[i].X(Y)' to a 16 bit integer as opposed to a 32 > bit integer? The variables you are using for the values are 32 bit. > Without looking at the IL produced, this would seem to force a conversion > from float(single) to a 16 bit integer, then it has to be cast to a 32 bit > integer for storage in the variable. > If you don't need to do the conversion to a 16 bit integer (short) then the > line > int y = ((short)(linePath.PathPoints[i].X))*PixelSize; > changes to > int y = ((int)(linePath.PathPoints[i].X))*PixelSize; > > Hope this helps. There are probably other minor optimizations, but these > are the ones I can see being helpful, especially the interval for the > progress bar update. > > Ray > > "Sam Davies" <sam@samdavies.co.uk> wrote in message > news:5600106.0401260458.715b748b@posting.google.com... > > Hi, > > > > I'm having some problems getting the required speed for a small app > > i'm currently writting. I rewrote the getPixel() fucntion that i > > thought was my orginal bottle neck, but i'm still taking 5-6 minutes > > to calcualte the score of around 6000 points. Does anyone have any > > suggestions as to other problems that may be slowing down this > > function?? > > > > > > private int returnArgb(GraphicsPath linePath, Bitmap Bmp) > > { > > int Argb; > > int score = 0; > > int RGBLightBlue = > (Color.LightBlue.R<<16)+(Color.LightBlue.G<<8)+(Color.LightBlue.B); > > int RGBWhite = (Color.White.R<<16)+(Color.White.G<<8)+(Color.White.B); > > int RGBRed = (Color.Red.R<<16)+(Color.Red.G<<8)+(Color.Red.B); > > int RGBDarkGreen = > (Color.DarkSeaGreen.R<<16)+(Color.DarkSeaGreen.G<<8)+(Color.DarkSeaGreen.B); > > > > paint.progressBar1.Maximum = linePath.PointCount; > > paint.statusBar1.Text = "Color Detection"; > > > > BitmapData bmData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, > > Bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); > > int stride = bmData.Stride; > > System.IntPtr Scan0 = bmData.Scan0; > > > > unsafe > > { > > int PixelSize = 3; > > byte blue, green, red; > > for(int i = 0; i<linePath.PointCount; i++) > > { > > paint.progressBar1.PerformStep(); > > int y = Convert.ToInt16(linePath.PathPoints[i].X); > > int x = Convert.ToInt16(linePath.PathPoints[i].Y); > > > > byte* row=(byte *)bmData.Scan0+(x*bmData.Stride); > > blue = row[(y*PixelSize)]; > > green = row[(y*PixelSize)+1]; > > red = row[(y*PixelSize)+2]; > > > > Argb = (red<<16)+(green<<8)+(blue); > > > > > > if(Argb == RGBLightBlue) > > continue; > > else if(Argb == RGBRed) > > { > > score = score+2; > > } > > else if(Argb == RGBWhite) > > { > > score = score+2; > > } > > else if(Argb == RGBDarkGreen) > > { > > score = score+4; > > } > > else > > score++; > > } > > } > > > > Bmp.UnlockBits(bmData); > > > > return score; > > } > > > > > > > > Regards > > Sam > >
Good points, [quoted text, click to view] > Third, I don't know if this will help performance or not, but the IL is a > little different (uses the dup opcode instead of ldarg a second time), but > you could use 'score+=2' instead of 'score=score+2'. I'm guessing the dup > opcode is more efficient due to already having the value on the stack and > just copying that value instead of having to process the value from the > variable a second time, but I don't know how much better
I wouldn't worry exceedingly about slightly different IL. In some cases, this will result the exact same JIT output. [quoted text, click to view] > Without looking at the IL produced, this would seem to force a conversion > from float(single) to a 16 bit integer, then it has to be cast to a 32 bit > integer for storage in the variable.
Using 32bit ints should be faster anyways. But, storing a 16bit int into a 32bit int doesnt have extra IL codes: conv.i2, stloc.x. -mike MVP [quoted text, click to view] > If you don't need to do the conversion to a 16 bit integer (short) then the > line > int y = ((short)(linePath.PathPoints[i].X))*PixelSize; > changes to > int y = ((int)(linePath.PathPoints[i].X))*PixelSize; > > Hope this helps. There are probably other minor optimizations, but these > are the ones I can see being helpful, especially the interval for the > progress bar update. > > Ray > > "Sam Davies" <sam@samdavies.co.uk> wrote in message > news:5600106.0401260458.715b748b@posting.google.com... > > Hi, > > > > I'm having some problems getting the required speed for a small app > > i'm currently writting. I rewrote the getPixel() fucntion that i > > thought was my orginal bottle neck, but i'm still taking 5-6 minutes > > to calcualte the score of around 6000 points. Does anyone have any > > suggestions as to other problems that may be slowing down this > > function?? > > > > > > private int returnArgb(GraphicsPath linePath, Bitmap Bmp) > > { > > int Argb; > > int score = 0; > > int RGBLightBlue = > (Color.LightBlue.R<<16)+(Color.LightBlue.G<<8)+(Color.LightBlue.B); > > int RGBWhite = (Color.White.R<<16)+(Color.White.G<<8)+(Color.White.B); > > int RGBRed = (Color.Red.R<<16)+(Color.Red.G<<8)+(Color.Red.B); > > int RGBDarkGreen = > (Color.DarkSeaGreen.R<<16)+(Color.DarkSeaGreen.G<<8)+(Color.DarkSeaGreen.B); > > > > paint.progressBar1.Maximum = linePath.PointCount; > > paint.statusBar1.Text = "Color Detection"; > > > > BitmapData bmData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, > > Bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); > > int stride = bmData.Stride; > > System.IntPtr Scan0 = bmData.Scan0; > > > > unsafe > > { > > int PixelSize = 3; > > byte blue, green, red; > > for(int i = 0; i<linePath.PointCount; i++) > > { > > paint.progressBar1.PerformStep(); > > int y = Convert.ToInt16(linePath.PathPoints[i].X); > > int x = Convert.ToInt16(linePath.PathPoints[i].Y); > > > > byte* row=(byte *)bmData.Scan0+(x*bmData.Stride); > > blue = row[(y*PixelSize)]; > > green = row[(y*PixelSize)+1]; > > red = row[(y*PixelSize)+2]; > > > > Argb = (red<<16)+(green<<8)+(blue); > > > > > > if(Argb == RGBLightBlue) > > continue; > > else if(Argb == RGBRed) > > { > > score = score+2; > > } > > else if(Argb == RGBWhite) > > { > > score = score+2; > > } > > else if(Argb == RGBDarkGreen) > > { > > score = score+4; > > } > > else > > score++; > > } > > } > > > > Bmp.UnlockBits(bmData); > > > > return score; > > } > > > > > > > > Regards > > Sam > >
A few comments: 1) Take a look at my FastBitmap class at: http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=6699aa41-7b59-40ec-a30d-da3afe63bd05 2) If you can use pointer arithmetic rather than multiplication, things will be much faster. 3) Try using a structure to be able to fetch out all values at once (see PixelData class in above example). 4) Be very careful about using progress bars in tight loops. That could be a big drain of resources. At the very least, try doing the update only every 10 or 100 steps. 5) Do your best to get rid of the convert calls -- Eric Gunnerson Visit the C# product team at http://www.csharp.net Eric's blog is at http://weblogs.asp.net/ericgu/ This posting is provided "AS IS" with no warranties, and confers no rights. [quoted text, click to view] "Michael Giagnocavo [MVP]" <mggUNSPAM@Atrevido.net> wrote in message news:eFyKi3p5DHA.2480@TK2MSFTNGP10.phx.gbl... > Good points, > > > Third, I don't know if this will help performance or not, but the IL is a > > little different (uses the dup opcode instead of ldarg a second time), but > > you could use 'score+=2' instead of 'score=score+2'. I'm guessing the dup > > opcode is more efficient due to already having the value on the stack and > > just copying that value instead of having to process the value from the > > variable a second time, but I don't know how much better > > I wouldn't worry exceedingly about slightly different IL. In some cases, > this will result the exact same JIT output. > > > Without looking at the IL produced, this would seem to force a conversion > > from float(single) to a 16 bit integer, then it has to be cast to a 32 bit > > integer for storage in the variable. > > Using 32bit ints should be faster anyways. But, storing a 16bit int into a > 32bit int doesnt have extra IL codes: conv.i2, stloc.x. > > -mike > MVP > > > If you don't need to do the conversion to a 16 bit integer (short) then > the > > line > > int y = ((short)(linePath.PathPoints[i].X))*PixelSize; > > changes to > > int y = ((int)(linePath.PathPoints[i].X))*PixelSize; > > > > Hope this helps. There are probably other minor optimizations, but these > > are the ones I can see being helpful, especially the interval for the > > progress bar update. > > > > Ray > > > > "Sam Davies" <sam@samdavies.co.uk> wrote in message > > news:5600106.0401260458.715b748b@posting.google.com... > > > Hi, > > > > > > I'm having some problems getting the required speed for a small app > > > i'm currently writting. I rewrote the getPixel() fucntion that i > > > thought was my orginal bottle neck, but i'm still taking 5-6 minutes > > > to calcualte the score of around 6000 points. Does anyone have any > > > suggestions as to other problems that may be slowing down this > > > function?? > > > > > > > > > private int returnArgb(GraphicsPath linePath, Bitmap Bmp) > > > { > > > int Argb; > > > int score = 0; > > > int RGBLightBlue = > > (Color.LightBlue.R<<16)+(Color.LightBlue.G<<8)+(Color.LightBlue.B); > > > int RGBWhite = (Color.White.R<<16)+(Color.White.G<<8)+(Color.White.B); > > > int RGBRed = (Color.Red.R<<16)+(Color.Red.G<<8)+(Color.Red.B); > > > int RGBDarkGreen = > > > (Color.DarkSeaGreen.R<<16)+(Color.DarkSeaGreen.G<<8)+(Color.DarkSeaGreen.B); > > > > > > paint.progressBar1.Maximum = linePath.PointCount; > > > paint.statusBar1.Text = "Color Detection"; > > > > > > BitmapData bmData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, > > > Bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); > > > int stride = bmData.Stride; > > > System.IntPtr Scan0 = bmData.Scan0; > > > > > > unsafe > > > { > > > int PixelSize = 3; > > > byte blue, green, red; > > > for(int i = 0; i<linePath.PointCount; i++) > > > { > > > paint.progressBar1.PerformStep(); > > > int y = Convert.ToInt16(linePath.PathPoints[i].X); > > > int x = Convert.ToInt16(linePath.PathPoints[i].Y); > > > > > > byte* row=(byte *)bmData.Scan0+(x*bmData.Stride); > > > blue = row[(y*PixelSize)]; > > > green = row[(y*PixelSize)+1]; > > > red = row[(y*PixelSize)+2]; > > > > > > Argb = (red<<16)+(green<<8)+(blue); > > > > > > > > > if(Argb == RGBLightBlue) > > > continue; > > > else if(Argb == RGBRed) > > > { > > > score = score+2; > > > } > > > else if(Argb == RGBWhite) > > > { > > > score = score+2; > > > } > > > else if(Argb == RGBDarkGreen) > > > { > > > score = score+4; > > > } > > > else > > > score++; > > > } > > > } > > > > > > Bmp.UnlockBits(bmData); > > > > > > return score; > > > } > > > > > > > > > > > > Regards > > > Sam > > > > >
hi Eric, Just been having a play with your fastbit class and its running much faster, i'm sure there are a few changes i can make to the function i have going at the moment, but i'd like to remove a bug that i can't seem to figure out. The graphics path i am passing in hold the co-ordinates for lines that either run vertically or horizotal across the screen. When a line is loaded that is horizontal the software runs fine, however, when the line is entered that is vertical at a certain point the loop throws an error. its obvious that somewhere i have not set up the correct widths and height but i'm strugglering to fix the problem. Any light you could shine on the mater would again be really appriciated. My function looks like this; int Argb = 0; int score = 0; int RGBLightBlue = (Color.LightBlue.R<<16)+(Color.LightBlue.G<<8)+(Color.LightBlue.B); int RGBWhite = (Color.White.R<<16)+(Color.White.G<<8)+(Color.White.B); int RGBRed = (Color.Red.R<<16)+(Color.Red.G<<8)+(Color.Red.B); int RGBDarkGreen = (Color.DarkSeaGreen.R<<16)+(Color.DarkSeaGreen.G<<8)+(Color.DarkSeaGreen.B); unsafe { FastBitmap fastBitmap = new FastBitmap(Bmp); fastBitmap.LockBitmap(); Point size = fastBitmap.Size; for (int x = 0; x < linePath.PointCount; x++) { PixelData* pPixel = fastBitmap[(int)linePath.PathPoints[x].X, (int)linePath.PathPoints[x].Y]; Argb = (pPixel->red<<16)+(pPixel->green<<8)+(pPixel->blue); pPixel++; if(Argb == RGBLightBlue) continue; else if(Argb == RGBRed) { score+=2; } else if(Argb == RGBWhite) { score+=2; } else if(Argb == RGBDarkGreen) { score+=4; } else score++; } fastBitmap.UnlockBitmap(); } Regards Sam [quoted text, click to view] "Eric Gunnerson [MS]" <ericgu@online.microsoft.com> wrote in message news:<OKLwGLd6DHA.2560@TK2MSFTNGP09.phx.gbl>... > A few comments: > > 1) Take a look at my FastBitmap class at: > http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=6699aa41-7b59-40ec-a30d-da3afe63bd05 > 2) If you can use pointer arithmetic rather than multiplication, things will > be much faster. > 3) Try using a structure to be able to fetch out all values at once (see > PixelData class in above example). > 4) Be very careful about using progress bars in tight loops. That could be a > big drain of resources. At the very least, try doing the update only every > 10 or 100 steps. > 5) Do your best to get rid of the convert calls > > > -- > Eric Gunnerson > > Visit the C# product team at http://www.csharp.net > Eric's blog is at http://weblogs.asp.net/ericgu/ > > This posting is provided "AS IS" with no warranties, and confers no rights. > "Michael Giagnocavo [MVP]" <mggUNSPAM@Atrevido.net> wrote in message > news:eFyKi3p5DHA.2480@TK2MSFTNGP10.phx.gbl... > > Good points, > > > > > Third, I don't know if this will help performance or not, but the IL is > a > > > little different (uses the dup opcode instead of ldarg a second time), > but > > > you could use 'score+=2' instead of 'score=score+2'. I'm guessing the > dup > > > opcode is more efficient due to already having the value on the stack > and > > > just copying that value instead of having to process the value from the > > > variable a second time, but I don't know how much better > > > > I wouldn't worry exceedingly about slightly different IL. In some cases, > > this will result the exact same JIT output. > > > > > Without looking at the IL produced, this would seem to force a > conversion > > > from float(single) to a 16 bit integer, then it has to be cast to a 32 > bit > > > integer for storage in the variable. > > > > Using 32bit ints should be faster anyways. But, storing a 16bit int into > a > > 32bit int doesnt have extra IL codes: conv.i2, stloc.x. > > > > -mike > > MVP > > > > > If you don't need to do the conversion to a 16 bit integer (short) then > the > > > line > > > int y = ((short)(linePath.PathPoints[i].X))*PixelSize; > > > changes to > > > int y = ((int)(linePath.PathPoints[i].X))*PixelSize; > > > > > > Hope this helps. There are probably other minor optimizations, but > these > > > are the ones I can see being helpful, especially the interval for the > > > progress bar update. > > > > > > Ray > > > > > > "Sam Davies" <sam@samdavies.co.uk> wrote in message > > > news:5600106.0401260458.715b748b@posting.google.com... > > > > Hi, > > > > > > > > I'm having some problems getting the required speed for a small app > > > > i'm currently writting. I rewrote the getPixel() fucntion that i > > > > thought was my orginal bottle neck, but i'm still taking 5-6 minutes > > > > to calcualte the score of around 6000 points. Does anyone have any > > > > suggestions as to other problems that may be slowing down this > > > > function?? > > > > > > > > > > > > private int returnArgb(GraphicsPath linePath, Bitmap Bmp) > > > > { > > > > int Argb; > > > > int score = 0; > > > > int RGBLightBlue = > (Color.LightBlue.R<<16)+(Color.LightBlue.G<<8)+(Color.LightBlue.B); > > > > int RGBWhite = > (Color.White.R<<16)+(Color.White.G<<8)+(Color.White.B); > > > > int RGBRed = (Color.Red.R<<16)+(Color.Red.G<<8)+(Color.Red.B); > > > > int RGBDarkGreen = > > > > > > (Color.DarkSeaGreen.R<<16)+(Color.DarkSeaGreen.G<<8)+(Color.DarkSeaGreen.B); > > > > > > > > paint.progressBar1.Maximum = linePath.PointCount; > > > > paint.statusBar1.Text = "Color Detection"; > > > > > > > > BitmapData bmData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, > > > > Bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); > > > > int stride = bmData.Stride; > > > > System.IntPtr Scan0 = bmData.Scan0; > > > > > > > > unsafe > > > > { > > > > int PixelSize = 3; > > > > byte blue, green, red; > > > > for(int i = 0; i<linePath.PointCount; i++) > > > > { > > > > paint.progressBar1.PerformStep(); > > > > int y = Convert.ToInt16(linePath.PathPoints[i].X); > > > > int x = Convert.ToInt16(linePath.PathPoints[i].Y); > > > > > > > > byte* row=(byte *)bmData.Scan0+(x*bmData.Stride); > > > > blue = row[(y*PixelSize)]; > > > > green = row[(y*PixelSize)+1]; > > > > red = row[(y*PixelSize)+2]; > > > > > > > > Argb = (red<<16)+(green<<8)+(blue); > > > > > > > > > > > > if(Argb == RGBLightBlue) > > > > continue; > > > > else if(Argb == RGBRed) > > > > { > > > > score = score+2; > > > > } > > > > else if(Argb == RGBWhite) > > > > { > > > > score = score+2; > > > > } > > > > else if(Argb == RGBDarkGreen) > > > > { > > > > score = score+4; > > > > } > > > > else > > > > score++; > > > > } > > > > }
What exactly does your method do? You could use Graphics.DrawPath to draw the path on an empty Bitmap and then analyze all Pixels on that Bitmap. Or you could set the Clipping Region of the Graphics objekt to that Path and then use Drawimage and this way filter out everything that doesn't belong to the path. -- cody Freeware Tools, Games and Humour http://www.deutronium.de.vu || http://www.deutronium.tk
Don't see what you're looking for? Try a search.
|
|
|