CODE to Test ALPHA Transparency

  • Thread starter tommaso.gastaldi
  • Start date
T

tommaso.gastaldi

In a previous post I have been asking about a way to test Alpha
Transparency.
Bob and Michael have kindly provided some ideas.

Here I would like to share the function I have prepared, for the
purpose to improve it.
Frankly, I am not clear about the exact meaning of some pixel format
(max, gdi, etc.) and I hope I have put them under the right "case". I
have made only some superficial test and it seems to work.
Note that the purpose is to test ALPHA transparency (not transparency
in indexed-color image) this is useful because some programs do not
support it (as for instance IE 6)
I enclose all the source, included the handler for a button (button1)
on a form.

The logic I use is to make first a "preliminary quick check", based on
the consideration that, if Alpha transparency is used, in the 95% of
the cases it "shows up" around the picture. If the check is
undeterminate, the user can specify to perform a full scan (this needs
to be improved much).

Please, suggest all the code improvement that are useful to improve
this test and it's
speed ...


Imports System.Drawing.Imaging

Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "
#End Region

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click

'Dialog to load an image from disk

Dim FileImage As String

Dim Ofd As New OpenFileDialog
With Ofd
.Filter = "All files (*.*)|*.*" & _
"|Bitmap files (*.bmp)|*.bmp" & _
"|Portable Network Graphics files (*.png)|*.png"
& _
"|Jpeg files (*.jpg)|*.jpg" & _
"|Tiff files (*.tif)|*.tif" & _
"|GIF files (*.gif)|*.gif" & _
"|Windows Meta files (*.wmf)|*.wmf" & _
"|Windows Icon files (*.ico)|*.ico"
If Not .ShowDialog.Equals(DialogResult.OK) Then Exit Sub
FileImage = .FileName
.Dispose()
End With

Dim b As Bitmap
Dim i As Image

Try
i = Image.FromFile(FileImage)
Catch ex As Exception
MsgBox("Invalid picture or unsupported format")
Exit Sub
End Try

If TypeOf (i) Is Bitmap Then
b = DirectCast(i, Bitmap)
MsgBox("Uses Alpha transparency: " & _
Me.ImageUsesAlphaTransparency(b, True).ToString)
Else
MsgBox("Not a bitmap")
End If

End Sub

Public Function ImageUsesAlphaTransparency(ByVal Bitmap As Bitmap,
_
ByVal FullCheck As
Boolean) As Boolean
With Bitmap

Select Case .PixelFormat
Case PixelFormat.Indexed, _
PixelFormat.Format16bppGrayScale, _
PixelFormat.Format16bppRgb555, _
PixelFormat.Format16bppRgb565, _
PixelFormat.Format1bppIndexed, _
PixelFormat.Format24bppRgb, _
PixelFormat.Format32bppRgb, _
PixelFormat.Format48bppRgb, _
PixelFormat.Format4bppIndexed, _
PixelFormat.Format8bppIndexed, _
PixelFormat.Max '(what's that?)

Return False

Case PixelFormat.Format16bppArgb1555, _
PixelFormat.Format32bppArgb, _
PixelFormat.Format32bppPArgb, _
PixelFormat.Format64bppArgb, _
PixelFormat.Format64bppPArgb, _
PixelFormat.Gdi, _
PixelFormat.Alpha, _
PixelFormat.PAlpha, _
PixelFormat.DontCare, _
PixelFormat.Canonical, _
PixelFormat.Undefined, _
PixelFormat.Extended

'Quick check of the 4 corners and center
'(as, usually, transparency is used around a
picture)

If .GetPixel(0, 0).A < 255 Then Return True
If .GetPixel(Bitmap.Width - 1, Bitmap.Height - 1).A
< 255 Then Return True
If .GetPixel(0, Bitmap.Height - 1).A < 255 Then
Return True
If .GetPixel(Bitmap.Width - 1, 0).A < 255 Then
Return True
If .GetPixel(Bitmap.Width \ 2, Bitmap.Height \ 2).A
< 255 Then Return True

'further checking needed (suggest code improvement)

If FullCheck Then
For x As Integer = 0 To .Width - 1
For y As Integer = 0 To .Height - 1
If .GetPixel(x, y).A < 255 Then Return
True
Next y
Next x
Return False
Else
Return True 'conservative choice
End If

Case Else
MsgBox("Unexpected event")
Return True

End Select

End With

End Function

End Class




-tommaso
 
M

Mick Doherty

Instead of the GetPixel method use LockBits.

You can see how I test for Alpha bits in the "Get Alpha Bitmap from 32 bit
Icon." example on my site:
http://www.dotnetrix.co.uk/misc.html

I like the quick test in your example and may incorporate that in mine.
 
T

tommaso.gastaldi

Yes Mick, you are right.

I was aware of that, but frankly I am too unfamiliar with it to try to
provide code useful for the community, and therefore, I was hoping that
someone who has experience with it, would contribute it to enhance the
scan part of the function.

You mean this (Your code):

For y = 0 To bmData.Height - 1
For x = 0 To bmData.Width - 1
Dim PixelColor As Color
PixelColor = Color.FromArgb(Marshal.ReadInt32(bmData.Scan0,
(bmData.Stride * y) + (4 * x)))
If PixelColor.A > 0 And PixelColor.A < 255 Then
IsAlphaBitmap = True
Exit For
End If
Next
If IsAlphaBitmap Then Exit For
Next

right? But I am afraid this won't work with all PixelFormats listed
under the "case" (?).

When you do the merge, will you be as kind as to show your final code?
I will be happy to collaborate, in case.

There are still some obscure areas: like some PixelFormat (max, gdi). I
am wondering what is "max" and if it should be moved in the "Alpha"
case (?)

-tom

Mick Doherty ha scritto:
 
M

Mick Doherty

Yes that's the part that I meant. It obviously needs a little work for your
requirements.

You don't need to scan anything that does not support Alpha.

The following is a list of ImageFormats that do support Alpha:
Format16bppArgb1555
Format32bppPArgb
Format64bppPArgb
Format32bppArgb
Format64bppArgb

A simple test for this is:
Bitmap.IsAlphaPixelFormat(myBitmap.PixelFormat)

You also need to know is the size of the scanbits. In my example it is 32
since I am working with a 32bit argb bitmap, but this may not be the case in
your image so you need to test it. A simple test is as follows:
Bitmap.GetPixelFormatSize(myBitmap.PixelFormat)

Now we know the size of the scanbits for each pixel we know that we need to
look at either 16, 32 or 64 bits at a time, and so know to use ReadInt16,
ReadInt32 or ReadInt64 with the System.Runtime.InteropServices.Marshal class

To improve slightly on my example for a 32 bit image, instead of converting
to Color you can simply get the Alpha value directly from the Int32 value
returned from Marshal.ReadInt32.
i.e. instead of:
PixelColor = Color.FromArgb(Marshal.ReadInt32(bmData.Scan0, >
(bmData.Stride * y) + (4 * x)))
If PixelColor.A > 0 AndAlso PixelColor.A < 255 Then

you could use:
Alpha = Marshal.ReadInt32(bmData.Scan0, > (bmData.Stride * y) + (4 * x))If Alpha > 0 AndAlso Alpha < 255 Then


This is where it starts to get tricky, and I am no expert in this field. I
did have a good MS reference for this when I was writing the method on my
site, but I have misplaced it and so will have to look for it again. I
wasn't really interested in any other formats at the time and so skipped
over it and only extracted the info that was relevant to what I was doing.

I seem to recall that there were some odd layouts and so you can't always
rely on a ScanLine being layed out as for instance:

ARGBARGBARGBARGB

because sometimes the Alpha channel is used as padding and so would result
in:

RGBRGBRGBRGBAAAA

....but this may only have been for non Alpha ImageFormats.

Whilst I am searching, the info on Bob Powell's site may be of some help,
specifically the info on this page which I believe may have come from the
same MS reference that I used:
http://www.bobpowell.net/lockingbits.htm
 
T

tommaso.gastaldi

Very good Mick . Very interesting information.

If the formats are only

Format16bppArgb1555
Format32bppPArgb
Format64bppPArgb
Format32bppArgb
Format64bppArgb

I think we should have all the pieces of info to write the optimized
function
(Bob is reporting on his site the correspondent formula to adjust the
addresses).

I am just wondering about:

PixelFormat.Max
PixelFormat.Gdi
PixelFormat.Alpha
PixelFormat.PAlpha
PixelFormat.DontCare
PixelFormat.Canonical
PixelFormat.Undefined
PixelFormat.Extended

what kind of images would fall into these categories ??
Or perhaps are they meant for bitwise combination ? It's quite
obscure...

Another doubt I have is why (in your code) the 0 value is excluded (no
color
contribution).

In case you succeed putting all pieces toghether let me know your
result.
I am very interested in it.

-tom

Mick Doherty ha scritto:
 
M

Mick Doherty

Very good Mick . Very interesting information.

If the formats are only

Format16bppArgb1555
Format32bppPArgb
Format64bppPArgb
Format32bppArgb
Format64bppArgb

I think we should have all the pieces of info to write the optimized
function
(Bob is reporting on his site the correspondent formula to adjust the
addresses).

I am just wondering about:

PixelFormat.Max
PixelFormat.Gdi
PixelFormat.Alpha
PixelFormat.PAlpha
PixelFormat.DontCare
PixelFormat.Canonical
PixelFormat.Undefined
PixelFormat.Extended

what kind of images would fall into these categories ??
Or perhaps are they meant for bitwise combination ? It's quite
obscure...

I believe these are just flags for the PixelFormat Enumeration and that no
Image will actually return these values as the PixelFormat, but I couldn't
say for certain.

For example PixelFormat.32bppArgb would contain the PixelFormat.Alpha flag
whereas PixelFormat.32bppPArgb would contain the PixelFormat.PAlpha flag.
Another doubt I have is why (in your code) the 0 value is excluded (no
color
contribution).

An Image may have been saved in a format that supports an Alpha Channel, but
it may not actually have any Alpha Content. These Images will return 0 in
the Alpha bit for Transparent Pixels and 255 for Solid Pixels and so could
be classed as supporting Transparency rather than Alpha. If you're testing
for Alpha content then it is very likely that it will be a value between On
and Off.
In case you succeed putting all pieces toghether let me know your
result.
I am very interested in it.

-tom

I'm a bit busy at the moment, but if I come up with anything I'll post it
here.
 
T

tommaso.gastaldi

Thank you Mick, you have provided a lot of useful information and
suggestions.

-tom

Mick Doherty ha scritto:
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top