By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,188 Members | 844 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,188 IT Pros & Developers. It's quick & easy.

How to duplicate emboss effect into second function

P: 7
I have two functions both Emboss and image but the first one works incredibly slow and the second doesn't match the desired effect from the first. I would like the image from the second function to be more "Dark Grey" like the first function. Can someone please help me.
#1 http://pastebin.com/QRX07iH9
#2 http://pastebin.com/1VQzQizy
Jan 19 '16 #1

✓ answered by IronRazer

Perhaps this will help. I cleaned the code up a bit and fixed a few things and it seems to produce the same exact image as the slow GetPixel and SetPixel methods.

You where stepping through the pixels incorrectly which i fixed in the example below. Also a 32bppArgb image has 4 bytes per pixel, not 2 which you where using if the PixelFormat of the image was 32bppArgb.

You will also notice that it will now keep the transparency of a 32BppArgb image such as a Png image often has instead of turning it gray too.

Expand|Select|Wrap|Line Numbers
  1.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  2.         Dim bmp As New Bitmap(PictureBox5.Image)
  3.         Dim bmpData As BitmapData = bmp.LockBits(New Rectangle(Point.Empty, bmp.Size), ImageLockMode.ReadWrite, bmp.PixelFormat)
  4.         Dim bpp As Integer = If((bmp.PixelFormat = PixelFormat.Format32bppArgb), 4, 3)
  5.         Dim data((bmpData.Stride * bmpData.Height) - 1) As Byte
  6.         Marshal.Copy(bmpData.Scan0, data, 0, data.Length)
  7.  
  8.         For i As Integer = 0 To data.Length - ((bpp + 1) + bmpData.Stride) Step bpp
  9.             data(i) = CByte(Math.Min(Math.Abs(CInt(data(i)) - CInt(data(i + bpp + bmpData.Stride))) + 128, 255)) 'Blue
  10.             data(i + 1) = CByte(Math.Min(Math.Abs(CInt(data(i + 1)) - CInt(data(i + bpp + 1 + bmpData.Stride))) + 128, 255)) 'Green
  11.             data(i + 2) = CByte(Math.Min(Math.Abs(CInt(data(i + 2)) - CInt(data(i + bpp + 2 + bmpData.Stride))) + 128, 255)) 'Red
  12.         Next
  13.  
  14.         Marshal.Copy(data, 0, bmpData.Scan0, data.Length)
  15.         bmp.UnlockBits(bmpData)
  16.  
  17.         If PictureBox5.Image IsNot Nothing Then
  18.             Try
  19.                 PictureBox5.Image.Dispose()
  20.             Catch ex As Exception
  21.             End Try
  22.         End If
  23.         PictureBox5.Image = bmp
  24.     End Sub
  25.  

Share this Question
Share on Google+
5 Replies


IronRazer
P: 82
Perhaps this will help. I cleaned the code up a bit and fixed a few things and it seems to produce the same exact image as the slow GetPixel and SetPixel methods.

You where stepping through the pixels incorrectly which i fixed in the example below. Also a 32bppArgb image has 4 bytes per pixel, not 2 which you where using if the PixelFormat of the image was 32bppArgb.

You will also notice that it will now keep the transparency of a 32BppArgb image such as a Png image often has instead of turning it gray too.

Expand|Select|Wrap|Line Numbers
  1.     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  2.         Dim bmp As New Bitmap(PictureBox5.Image)
  3.         Dim bmpData As BitmapData = bmp.LockBits(New Rectangle(Point.Empty, bmp.Size), ImageLockMode.ReadWrite, bmp.PixelFormat)
  4.         Dim bpp As Integer = If((bmp.PixelFormat = PixelFormat.Format32bppArgb), 4, 3)
  5.         Dim data((bmpData.Stride * bmpData.Height) - 1) As Byte
  6.         Marshal.Copy(bmpData.Scan0, data, 0, data.Length)
  7.  
  8.         For i As Integer = 0 To data.Length - ((bpp + 1) + bmpData.Stride) Step bpp
  9.             data(i) = CByte(Math.Min(Math.Abs(CInt(data(i)) - CInt(data(i + bpp + bmpData.Stride))) + 128, 255)) 'Blue
  10.             data(i + 1) = CByte(Math.Min(Math.Abs(CInt(data(i + 1)) - CInt(data(i + bpp + 1 + bmpData.Stride))) + 128, 255)) 'Green
  11.             data(i + 2) = CByte(Math.Min(Math.Abs(CInt(data(i + 2)) - CInt(data(i + bpp + 2 + bmpData.Stride))) + 128, 255)) 'Red
  12.         Next
  13.  
  14.         Marshal.Copy(data, 0, bmpData.Scan0, data.Length)
  15.         bmp.UnlockBits(bmpData)
  16.  
  17.         If PictureBox5.Image IsNot Nothing Then
  18.             Try
  19.                 PictureBox5.Image.Dispose()
  20.             Catch ex As Exception
  21.             End Try
  22.         End If
  23.         PictureBox5.Image = bmp
  24.     End Sub
  25.  
Jan 21 '16 #2

P: 7
Wow thank you so much is there any way I can tell the FPS like a timer ?
Jan 24 '16 #3

IronRazer
P: 82
I don`t quite understand what you mean. FPS would indicate frames per second to me so, do you mean you want to know how many images can be converted per second using this method?

If so, you can use the StopWatch class to measure how many milliseconds it takes from the start to the end of the whole conversion. Below is a link to the msdn documents on the StopWatch class. You can read about it and find an example of using it there.

https://msdn.microsoft.com/en-us/lib...vs.110%29.aspx
Jan 25 '16 #4

P: 7
Yeah I am applying this to a live image feed. It gets about 60 FPS now.
Feb 5 '16 #5

P: 7
Look guys i'm at a total loss. My effect is nice and it runs fast but the effect does not match the one i'm trying to duplicate wondering if anyone can help me.


That is the effect i'm trying to create. This is my effect currently


Am I even on the right path ?
Here is the finalized code.
Expand|Select|Wrap|Line Numbers
  1.  Private Function EdgeDetect(bmp As Bitmap) As Bitmap
  2.         'convert any input bitmap into jpg just to make sure to have the correct byte order
  3.         If Not bmp.RawFormat.Equals(ImageFormat.Jpeg) Then
  4.             Using msJPG As New IO.MemoryStream()
  5.                 bmp.Save(msJPG, ImageFormat.Jpeg)
  6.                 bmp = CType(Image.FromStream(msJPG), Bitmap)
  7.             End Using
  8.         End If
  9.         'setting up the lockbits
  10.         Dim raz As Integer = bmp.Height \ 3
  11.         Dim height As Integer = bmp.Height
  12.         Dim width As Integer = bmp.Width
  13.         Dim rect As New Rectangle(Point.Empty, bmp.Size)
  14.         Dim bmpData As BitmapData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat)
  15.         Dim bpp As Integer = If((bmp.PixelFormat = PixelFormat.Format32bppArgb), 2, 3)
  16.         Dim size As Integer = bmpData.Stride * bmpData.Height
  17.         Dim data As Byte() = New Byte(size - 1) {}
  18.         Dim result As Byte() = New Byte(size - 1) {}
  19.         Marshal.Copy(bmpData.Scan0, data, 0, size)
  20.         Marshal.Copy(bmpData.Scan0, result, 0, size) 'duplicate so that edge finding can run in parallel without using pixels as samples that have already been processed themselves
  21.         'edge detection
  22.         Dim stride As Integer = bmpData.Stride
  23.         'convert to grayscale first, makes finding edges cheaper later
  24.         Parallel.For(0, width, Sub(totallynewX)
  25.                                    Dim totallynewi As Integer
  26.                                    For totallynewY As Integer = 0 To height - 1
  27.                                        totallynewi = totallynewY * stride + totallynewX * bpp
  28.                                        Dim avg As Byte = CByte(Math.Min(data(totallynewi) * 0.299 + data(totallynewi + 1) * 0.587 + data(totallynewi + 2) * 0.114, 255)) 'formula for accurate grayscale
  29.                                        result(totallynewi) = avg
  30.                                        result(totallynewi + 1) = avg
  31.                                        result(totallynewi + 2) = avg
  32.                                    Next
  33.                                End Sub)
  34.  
  35.         'now find edges
  36.         Parallel.For(0, height, Sub(horizontal)
  37.                                     Dim pixel1, pixel2 As Integer
  38.                                     Dim total, index As Integer
  39.                                     For vertical As Integer = 0 To width - 1
  40.                                         Dim offset As Integer = 1
  41.                                         If horizontal = height - 1 OrElse vertical = width - 1 Then offset = 0
  42.                                         index = horizontal * stride + vertical * bpp
  43.                                         pixel1 = data(index)
  44.                                         index = (horizontal + offset) * stride + (vertical + offset) * bpp
  45.                                         pixel2 = data(index)
  46.                                         total = Math.Min(Math.Abs(pixel1 - pixel2) + 128, 255)
  47.                                         index = horizontal * stride + vertical * bpp
  48.                                         result(index) = CByte(total)
  49.                                         result(index + 1) = CByte(total)
  50.                                         result(index + 2) = CByte(total)
  51.                                     Next
  52.                                 End Sub)
  53.  
  54.         Marshal.Copy(result, 0, bmpData.Scan0, data.Length)
  55.         bmp.UnlockBits(bmpData)
  56.         Return bmp
  57.     End Function
This provides me with the second image effect.
Feb 5 '16 #6

Post your reply

Sign in to post your reply or Sign up for a free account.