-
Mar 16th, 2023, 06:39 PM
#1
[RESOLVED] Problem sharpening semi-transparent image
I found this code for sharpening images online. I haven't done much testing with it yet, but i do know it's ruining the transparent parts of my bitmaps.
Can anyone give a solution, that retains the transparent pixels?
Code:
Imports System.Runtime.InteropServices
Imports System.Drawing.Imaging
Public Class Convolution
Public Sub Convolution3x3(ByRef bmp As Bitmap)
Dim Factor As Integer = Matrix.Factor
If Factor = 0 Then
Return
End If
Dim TopLeft As Integer = Matrix.TopLeft
Dim TopMid As Integer = Matrix.TopMid
Dim TopRight As Integer = Matrix.TopRight
Dim MidLeft As Integer = Matrix.MidLeft
Dim MidRight As Integer = Matrix.MidRight
Dim BottomLeft As Integer = Matrix.BottomLeft
Dim BottomMid As Integer = Matrix.BottomMid
Dim BottomRight As Integer = Matrix.BottomRight
Dim Pixel As Integer = Matrix.Pixel
Dim Offset As Integer = Matrix.Offset
Dim TempBmp As Bitmap = bmp.Clone()
Dim bmpData As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
Dim TempBmpData As BitmapData = TempBmp.LockBits(New Rectangle(0, 0, TempBmp.Width, TempBmp.Height), ImageLockMode.[ReadOnly], PixelFormat.Format24bppRgb)
Dim ptr As IntPtr = bmpData.Scan0
Dim TempPtr As IntPtr = TempBmpData.Scan0
Dim Pix As Integer = 0
Dim Stride As Integer = bmpData.Stride
Dim DoubleStride As Integer = Stride * 2
Dim Width As Integer = bmp.Width - 2
Dim Height As Integer = bmp.Height - 2
Dim stopAddress As Integer = CInt(CInt(ptr)) + bmpData.Stride * bmpData.Height
For y As Integer = 0 To Height - 1
For x As Integer = 0 To Width - 1
Pix = (((((Marshal.ReadByte(CInt(TempPtr) + 2) * TopLeft) + (Marshal.ReadByte(CInt(TempPtr) + 5) * TopMid) + (Marshal.ReadByte(CInt(TempPtr) + 8) * TopRight)) + _
((Marshal.ReadByte(CInt(TempPtr) + 2 + Stride) * MidLeft) + (Marshal.ReadByte(CInt(TempPtr) + 5 + Stride) * Pixel) + (Marshal.ReadByte(CInt(TempPtr) + 8 + Stride) * MidRight)) + _
((Marshal.ReadByte(CInt(TempPtr) + 2 + DoubleStride) * BottomLeft) + (Marshal.ReadByte(CInt(TempPtr) + 5 + DoubleStride) * BottomMid) + (Marshal.ReadByte(CInt(TempPtr) + 8 + DoubleStride) * BottomRight))) \ Factor) + Offset)
If Pix < 0 Then
Pix = 0
ElseIf Pix > 255 Then
Pix = 255
End If
Marshal.WriteByte(CInt(ptr) + 5 + Stride, CByte(Pix))
Pix = (((((Marshal.ReadByte(CInt(TempPtr) + 1) * TopLeft) + (Marshal.ReadByte(CInt(TempPtr) + 4) * TopMid) + (Marshal.ReadByte(CInt(TempPtr) + 7) * TopRight)) + _
((Marshal.ReadByte(CInt(TempPtr) + 1 + Stride) * MidLeft) + (Marshal.ReadByte(CInt(TempPtr) + 4 + Stride) * Pixel) + (Marshal.ReadByte(CInt(TempPtr) + 7 + Stride) * MidRight)) + _
((Marshal.ReadByte(CInt(TempPtr) + 1 + DoubleStride) * BottomLeft) + (Marshal.ReadByte(CInt(TempPtr) + 4 + DoubleStride) * BottomMid) + (Marshal.ReadByte(CInt(TempPtr) + 7 + DoubleStride) * BottomRight))) \ Factor) + Offset)
If Pix < 0 Then
Pix = 0
ElseIf Pix > 255 Then
Pix = 255
End If
Marshal.WriteByte(CInt(ptr) + 4 + Stride, CByte(Pix))
Pix = (((((Marshal.ReadByte(CInt(TempPtr)) * TopLeft) + (Marshal.ReadByte(CInt(TempPtr) + 3) * TopMid) + (Marshal.ReadByte(CInt(TempPtr) + 6) * TopRight)) + _
((Marshal.ReadByte(CInt(TempPtr) + Stride) * MidLeft) + (Marshal.ReadByte(CInt(TempPtr) + 3 + Stride) * Pixel) + (Marshal.ReadByte(CInt(TempPtr) + 6 + Stride) * MidRight)) + _
((Marshal.ReadByte(CInt(TempPtr) + DoubleStride) * BottomLeft) + (Marshal.ReadByte(CInt(TempPtr) + 3 + DoubleStride) * BottomMid) + (Marshal.ReadByte(CInt(TempPtr) + 6 + DoubleStride) * BottomRight))) \ Factor) + Offset)
If Pix < 0 Then
Pix = 0
ElseIf Pix > 255 Then
Pix = 255
End If
Marshal.WriteByte(CInt(ptr) + 3 + Stride, CByte(Pix))
ptr = CInt(ptr) + 3
TempPtr = CInt(TempPtr) + 3
Next
Next
bmp.UnlockBits(bmpData)
TempBmp.UnlockBits(TempBmpData)
End Sub
Public Property Matrix() As ConvolutionMatrix
Get
Return m_Matrix
End Get
Set(ByVal value As ConvolutionMatrix)
m_Matrix = value
End Set
End Property
Private m_Matrix As ConvolutionMatrix
End Class
Code:
Public Class ConvolutionMatrix
Public Sub New()
Pixel = 1
Factor = 1
End Sub
Public Sub Apply(ByVal Val As Integer)
TopLeft = Val
TopMid = Val
TopRight = Val
MidLeft = Val
MidRight = Val
BottomLeft = Val
BottomMid = Val
BottomRight = Val
Pixel = Val
End Sub
Public Property TopLeft() As Integer
Get
Return m_TopLeft
End Get
Set(ByVal value As Integer)
m_TopLeft = value
End Set
End Property
Private m_TopLeft As Integer
Public Property TopMid() As Integer
Get
Return m_TopMid
End Get
Set(ByVal value As Integer)
m_TopMid = value
End Set
End Property
Private m_TopMid As Integer
Public Property TopRight() As Integer
Get
Return m_TopRight
End Get
Set(ByVal value As Integer)
m_TopRight = value
End Set
End Property
Private m_TopRight As Integer
Public Property MidLeft() As Integer
Get
Return m_MidLeft
End Get
Set(ByVal value As Integer)
m_MidLeft = value
End Set
End Property
Private m_MidLeft As Integer
Public Property MidRight() As Integer
Get
Return m_MidRight
End Get
Set(ByVal value As Integer)
m_MidRight = value
End Set
End Property
Private m_MidRight As Integer
Public Property BottomLeft() As Integer
Get
Return m_BottomLeft
End Get
Set(ByVal value As Integer)
m_BottomLeft = value
End Set
End Property
Private m_BottomLeft As Integer
Public Property BottomMid() As Integer
Get
Return m_BottomMid
End Get
Set(ByVal value As Integer)
m_BottomMid = value
End Set
End Property
Private m_BottomMid As Integer
Public Property BottomRight() As Integer
Get
Return m_BottomRight
End Get
Set(ByVal value As Integer)
m_BottomRight = value
End Set
End Property
Private m_BottomRight As Integer
Public Property Pixel() As Integer
Get
Return m_Pixel
End Get
Set(ByVal value As Integer)
m_Pixel = value
End Set
End Property
Private m_Pixel As Integer
Public Property Factor() As Integer
Get
Return m_Factor
End Get
Set(ByVal value As Integer)
m_Factor = value
End Set
End Property
Private m_Factor As Integer
Public Property Offset() As Integer
Get
Return m_Offset
End Get
Set(ByVal value As Integer)
m_Offset = value
End Set
End Property
Private m_Offset As Integer
End Class
Code:
Public Shared Sub ApplySharpen(ByRef bmp As Bitmap, ByVal weight As Integer)
Dim m As New ConvolutionMatrix()
m.Apply(0)
m.Pixel = weight
m.TopMid = -2
m.MidLeft = -2
m.MidRight = -2
m.BottomMid = -2
m.Factor = weight - 8
Dim C As New Convolution()
C.Matrix = m
C.Convolution3x3(bmp)
End Sub
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Mar 16th, 2023, 07:32 PM
#2
Re: Problem sharpening semi-transparent image
I don't know, but I suppose you could try checking the Alpha value of the destination pixel you are working on, and if it is not 255, then skip all the processing so you don't modify that pixel, i.e. you won't take values from the surrounding pixels and modify the transparent/translucent pixel.
I think, looking at the code, I would have to watch it work to understand where the alpha value to be check would be in the loop.
A quick look at the code seems to suggest the loop is looking at a number of pixels around a reference pixel and then writing the result to a pixel above and to the right of the reference pixel being pointed at in the loop, so it would be the alpha value of the pixel the line above and to the right (thinking that the pixels are stored from the bottom up) that is being modified.
"Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930
-
Mar 17th, 2023, 01:46 PM
#3
Re: Problem sharpening semi-transparent image
That was my initial thoughts about it too, but I also can’t see where to test the Alpha value of the destination pixel, or even how to test the alpha value of the destination pixel…
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Mar 17th, 2023, 01:49 PM
#4
Re: Problem sharpening semi-transparent image
@passel… I can put together a quick test app, if you wouldn’t mind taking a look and want to see it running?
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Mar 17th, 2023, 04:47 PM
#5
Re: Problem sharpening semi-transparent image
Here's the test project. I've tidied the code significantly, making it error free was a task and a half
Sharpen_Image_Test.zip
The relevant code...
Code:
Public Sub Convolution3x3(ByRef bmp As Bitmap)
Dim Factor As Integer = Matrix.Factor
If Factor = 0 Then
Return
End If
Dim TopLeft As Integer = Matrix.TopLeft
Dim TopMid As Integer = Matrix.TopMid
Dim TopRight As Integer = Matrix.TopRight
Dim MidLeft As Integer = Matrix.MidLeft
Dim MidRight As Integer = Matrix.MidRight
Dim BottomLeft As Integer = Matrix.BottomLeft
Dim BottomMid As Integer = Matrix.BottomMid
Dim BottomRight As Integer = Matrix.BottomRight
Dim Pixel As Integer = Matrix.Pixel
Dim Offset As Integer = Matrix.Offset
Dim TempBmp As Bitmap = DirectCast(bmp.Clone(), Bitmap)
Dim bmpData As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
Dim TempBmpData As BitmapData = TempBmp.LockBits(New Rectangle(0, 0, TempBmp.Width, TempBmp.Height), ImageLockMode.[ReadOnly], PixelFormat.Format24bppRgb)
Dim ptr As Integer = bmpData.Scan0.ToInt32
Dim TempPtr As Integer = TempBmpData.Scan0.ToInt32
Dim Pix As Integer = 0
Dim Stride As Integer = bmpData.Stride
Dim DoubleStride As Integer = Stride * 2
Dim Width As Integer = bmp.Width - 2
Dim Height As Integer = bmp.Height - 2
Dim stopAddress As Integer = ptr + bmpData.Stride * bmpData.Height
For y As Integer = 0 To Height - 1
For x As Integer = 0 To Width - 1
Pix = (((Marshal.ReadByte(New IntPtr((TempPtr + 2))) * TopLeft + _
Marshal.ReadByte(New IntPtr((TempPtr + 5))) * TopMid + _
Marshal.ReadByte(New IntPtr((TempPtr + 8))) * TopRight + _
Marshal.ReadByte(New IntPtr((TempPtr + 2 + Stride))) * MidLeft + _
Marshal.ReadByte(New IntPtr((TempPtr + 5 + Stride))) * Pixel + _
Marshal.ReadByte(New IntPtr((TempPtr + 8 + Stride))) * MidRight + _
Marshal.ReadByte(New IntPtr((TempPtr + 2 + DoubleStride))) * BottomLeft + _
Marshal.ReadByte(New IntPtr((TempPtr + 5 + DoubleStride))) * BottomMid + _
Marshal.ReadByte(New IntPtr((TempPtr + 8 + DoubleStride))) * BottomRight) \ _
Factor) + Offset)
If Pix < 0 Then
Pix = 0
ElseIf Pix > 255 Then
Pix = 255
End If
'Dim b As Byte = Marshal.ReadByte(New IntPtr(ptr + 5 + Stride))
'If b Then ' how to detect if dest pixel is transparent???
Marshal.WriteByte(New IntPtr(ptr + 5 + Stride), CByte(Pix))
Pix = (((Marshal.ReadByte(New IntPtr((TempPtr + 1))) * TopLeft + _
Marshal.ReadByte(New IntPtr((TempPtr + 4))) * TopMid + _
Marshal.ReadByte(New IntPtr((TempPtr + 7))) * TopRight + _
Marshal.ReadByte(New IntPtr((TempPtr + 1 + Stride))) * MidLeft + _
Marshal.ReadByte(New IntPtr((TempPtr + 1 + Stride))) * Pixel + _
Marshal.ReadByte(New IntPtr((TempPtr + 4 + Stride))) * MidRight + _
Marshal.ReadByte(New IntPtr((TempPtr + 1 + DoubleStride))) * BottomLeft + _
Marshal.ReadByte(New IntPtr((TempPtr + 4 + DoubleStride))) * BottomMid + _
Marshal.ReadByte(New IntPtr((TempPtr + 7 + DoubleStride))) * BottomRight) \ _
Factor) + Offset)
If Pix < 0 Then
Pix = 0
ElseIf Pix > 255 Then
Pix = 255
End If
'b = Marshal.ReadByte(New IntPtr(ptr + 4 + Stride))
'If b Then ' how to detect if dest pixel is transparent???
Marshal.WriteByte(New IntPtr(ptr + 4 + Stride), CByte(Pix))
Pix = (((Marshal.ReadByte(New IntPtr((TempPtr))) * TopLeft + _
Marshal.ReadByte(New IntPtr((TempPtr + 3))) * TopMid + _
Marshal.ReadByte(New IntPtr((TempPtr + 6))) * TopRight + _
Marshal.ReadByte(New IntPtr((TempPtr + Stride))) * MidLeft + _
Marshal.ReadByte(New IntPtr((TempPtr + 3 + Stride))) * Pixel + _
Marshal.ReadByte(New IntPtr((TempPtr + 6 + Stride))) * MidRight + _
Marshal.ReadByte(New IntPtr((TempPtr + DoubleStride))) * BottomLeft + _
Marshal.ReadByte(New IntPtr((TempPtr + 3 + DoubleStride))) * BottomMid + _
Marshal.ReadByte(New IntPtr((TempPtr + 6 + DoubleStride))) * BottomRight) \ _
Factor) + Offset)
If Pix < 0 Then
Pix = 0
ElseIf Pix > 255 Then
Pix = 255
End If
'b = Marshal.ReadByte(New IntPtr(ptr + 3 + Stride))
'If b Then ' how to detect if dest pixel is transparent???
Marshal.WriteByte(New IntPtr(ptr + 3 + Stride), CByte(Pix))
ptr += 3
TempPtr += 3
Next
Next
bmp.UnlockBits(bmpData)
TempBmp.UnlockBits(TempBmpData)
End Sub
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Mar 19th, 2023, 09:06 PM
#6
Re: Problem sharpening semi-transparent image
Looking at that code, I would expect the Alpha is being stripped off, and all the transparent pixels would end up being black.
It appears you're converting the pixels to 24bpp which ignores the Alpha, when putting the pixels into a byte array.
That also explains why the destination offsets of 3,4,5 didn't make sense to me. I would have expected 4,5,6 or 5,6,7 depending on which of the four bytes was the alpha byte.
i.e. the first pixel would be at offsets 0,1,2,3 and the second at 4,5,6,7 and third at 8,... if there were 32-bits per pixel.
But with 24-bpp the first pixel would be at offset 0,1,2 and the second at 3,4,5 and 3,4,5 offsets is what is in your code for the WriteBytes.
So, the sharpening code is expecting 24-bit rgb, not 32-bit argb.
"Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930
-
Mar 19th, 2023, 09:31 PM
#7
Re: Problem sharpening semi-transparent image
I'm a little confused by the code. I've seen similar before, loads of times, but i've never attempted to use it. Would it be very difficult to modify that to use 32bpp ?
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Mar 19th, 2023, 10:06 PM
#8
Re: Problem sharpening semi-transparent image
Actually, I think i'll abandon this image sharpening. It was for an icon editing app, and there weren't any encouraging results before the transparency problem, so no big loss...
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|