ImageList problems with semi transparent images

Y

Yuval Naveh

Hello,
I have encountered a problem while trying to display images in the
ListView control.
I am using Visual Studio 2003/C# on windows 2000 professional SP4.
My images are 32 bit PNG with alpha channel that has 256 levels.
After adding them to an ImageList component, and attaching the image list
to a list view, the images show thier alpha channel pixels as opaque pixels.
The problem seems to be with ImageList.
This subject has come up already in this newsgroup, and I saw no solution
for the problem.

Someone posted an untested code that is supposed to fix the problem, it
compiles and runs but does not work.

Can anyone suggest a solution (a working and tested code)?

Thanks
Yuval Naveh
Actimize
Israel

The code that was supposed to fix the problem:

[DllImport("comctl32.dll")]
static extern bool ImageList_Add( IntPtr hImageList, IntPtr hBitmap,
IntPtr hMask );
[DllImport("kernel32.dll")]
static extern bool RtlMoveMemory( IntPtr dest, IntPtr source, int
dwcount);
[DllImport("gdi32.dll")]
static extern IntPtr CreateDIBSection(IntPtr hdc, [In,
MarshalAs(UnmanagedType.LPStruct)] BITMAPINFO pbmi, uint iUsage, out IntPtr
ppvBits, IntPtr hSection, uint dwOffset);

[StructLayout(LayoutKind.Explicit)]
public class BITMAPINFO
{
[FieldOffset(0)]
public Int32 biSize;
[FieldOffset(4)]
public Int32 biWidth;
[FieldOffset(8)]
public Int32 biHeight;
[FieldOffset(12)]
public Int16 biPlanes;
[FieldOffset(14)]
public Int16 biBitCount;
[FieldOffset(16)]
public Int32 biCompression;
[FieldOffset(20)]
public Int32 biSizeImage;
[FieldOffset(24)]
public Int32 biXPelsPerMeter;
[FieldOffset(28)]
public Int32 biYPelsPerMeter;
[FieldOffset(32)]
public Int32 biClrUsed;
[FieldOffset(36)]
public Int32 biClrImportant;
[FieldOffset(40)]
public Int32 colors;
};

void AddPNGToImageList( ImageList il, string szFileName )
{
Bitmap bm = new Bitmap( szFileName );
IntPtr hBitmap, ppvBits;
BITMAPINFO bmi = new BITMAPINFO();

bmi.biSize = 40;
bmi.biBitCount = 32;
bmi.biPlanes = 1;
bmi.biWidth = bm.Width;
bmi.biHeight = bm.Height;
hBitmap = CreateDIBSection( new IntPtr(0), bmi, 0, out ppvBits, new
IntPtr(0), 0 );
BitmapData bitmapData;
Rectangle rect = new Rectangle(0, 0, bm.Width, bm.Height );
bitmapData = bm.LockBits( rect, ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb );
IntPtr pixels = bitmapData.Scan0;
RtlMoveMemory( ppvBits, pixels, bm.Height*bitmapData.Stride );
bm.UnlockBits( bitmapData );
ImageList_Add( il.Handle, hBitmap, new IntPtr(0) );
}
 
N

Neal Andrews

I have worked with the imagelist control but with the .net listview control.

The first thing is are you using a manifest
For the imagelist to support 32bpp images you need a manifest file or call
the following in .Net V1.1
Application.EnableVisualStyles
Application.DoEvents '(More Bug fixes)

If the images are still not displayed correctly then it maybe that the
images in the imagelist have lost there alpha channel (there are some bugs
with the imagelist control, where the images loose there alpha channel at
unexpected times when you add further images to the list.)

I have not used the ListView control yet so I cannot say how it is drawing
the images. When drawing 32bpp images from the imagelist control you must
use the Draw methods on the ImageList control and not the Draw Methods on
the Graphics object for the alpha channel to be drawn correctly. Another
problem with the ImageList control is that if you scale any images using the
draw methods on the imagelist control then the alpha channel info is also
lost. So you have to use the original win 32 api ImageList_DrawEx to draw
the scaled images from the imagelist control. I have submitted this as a bug
to MS, but as usual it's not a bug but a limitation (by design) of the
imagelist control, which means it is a bug but MS are not prepared to fix it
anytime soon.

Regards
Neal


Yuval Naveh said:
Hello,
I have encountered a problem while trying to display images in the
ListView control.
I am using Visual Studio 2003/C# on windows 2000 professional SP4.
My images are 32 bit PNG with alpha channel that has 256 levels.
After adding them to an ImageList component, and attaching the image list
to a list view, the images show thier alpha channel pixels as opaque pixels.
The problem seems to be with ImageList.
This subject has come up already in this newsgroup, and I saw no solution
for the problem.

Someone posted an untested code that is supposed to fix the problem, it
compiles and runs but does not work.

Can anyone suggest a solution (a working and tested code)?

Thanks
Yuval Naveh
Actimize
Israel

The code that was supposed to fix the problem:

[DllImport("comctl32.dll")]
static extern bool ImageList_Add( IntPtr hImageList, IntPtr hBitmap,
IntPtr hMask );
[DllImport("kernel32.dll")]
static extern bool RtlMoveMemory( IntPtr dest, IntPtr source, int
dwcount);
[DllImport("gdi32.dll")]
static extern IntPtr CreateDIBSection(IntPtr hdc, [In,
MarshalAs(UnmanagedType.LPStruct)] BITMAPINFO pbmi, uint iUsage, out IntPtr
ppvBits, IntPtr hSection, uint dwOffset);

[StructLayout(LayoutKind.Explicit)]
public class BITMAPINFO
{
[FieldOffset(0)]
public Int32 biSize;
[FieldOffset(4)]
public Int32 biWidth;
[FieldOffset(8)]
public Int32 biHeight;
[FieldOffset(12)]
public Int16 biPlanes;
[FieldOffset(14)]
public Int16 biBitCount;
[FieldOffset(16)]
public Int32 biCompression;
[FieldOffset(20)]
public Int32 biSizeImage;
[FieldOffset(24)]
public Int32 biXPelsPerMeter;
[FieldOffset(28)]
public Int32 biYPelsPerMeter;
[FieldOffset(32)]
public Int32 biClrUsed;
[FieldOffset(36)]
public Int32 biClrImportant;
[FieldOffset(40)]
public Int32 colors;
};

void AddPNGToImageList( ImageList il, string szFileName )
{
Bitmap bm = new Bitmap( szFileName );
IntPtr hBitmap, ppvBits;
BITMAPINFO bmi = new BITMAPINFO();

bmi.biSize = 40;
bmi.biBitCount = 32;
bmi.biPlanes = 1;
bmi.biWidth = bm.Width;
bmi.biHeight = bm.Height;
hBitmap = CreateDIBSection( new IntPtr(0), bmi, 0, out ppvBits, new
IntPtr(0), 0 );
BitmapData bitmapData;
Rectangle rect = new Rectangle(0, 0, bm.Width, bm.Height );
bitmapData = bm.LockBits( rect, ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb );
IntPtr pixels = bitmapData.Scan0;
RtlMoveMemory( ppvBits, pixels, bm.Height*bitmapData.Stride );
bm.UnlockBits( bitmapData );
ImageList_Add( il.Handle, hBitmap, new IntPtr(0) );
}
 
Y

Yuval Naveh

Neal,
Thanks but your reply did not really help me.
My problem is that ImageList when connected to any control (ListView,
TreeView, ComboBox) will not show the image properly if the image as 256
levels in the alpha channel.
The alpha pixels become opaque.
I do not want to custom draw each element in each control, so Draw()
method will not do the trick.

Any other ideas?

Yuval

Neal Andrews said:
I have worked with the imagelist control but with the .net listview control.

The first thing is are you using a manifest
For the imagelist to support 32bpp images you need a manifest file or call
the following in .Net V1.1
Application.EnableVisualStyles
Application.DoEvents '(More Bug fixes)

If the images are still not displayed correctly then it maybe that the
images in the imagelist have lost there alpha channel (there are some bugs
with the imagelist control, where the images loose there alpha channel at
unexpected times when you add further images to the list.)

I have not used the ListView control yet so I cannot say how it is drawing
the images. When drawing 32bpp images from the imagelist control you must
use the Draw methods on the ImageList control and not the Draw Methods on
the Graphics object for the alpha channel to be drawn correctly. Another
problem with the ImageList control is that if you scale any images using the
draw methods on the imagelist control then the alpha channel info is also
lost. So you have to use the original win 32 api ImageList_DrawEx to draw
the scaled images from the imagelist control. I have submitted this as a bug
to MS, but as usual it's not a bug but a limitation (by design) of the
imagelist control, which means it is a bug but MS are not prepared to fix it
anytime soon.

Regards
Neal


Yuval Naveh said:
Hello,
I have encountered a problem while trying to display images in the
ListView control.
I am using Visual Studio 2003/C# on windows 2000 professional SP4.
My images are 32 bit PNG with alpha channel that has 256 levels.
After adding them to an ImageList component, and attaching the image list
to a list view, the images show thier alpha channel pixels as opaque pixels.
The problem seems to be with ImageList.
This subject has come up already in this newsgroup, and I saw no solution
for the problem.

Someone posted an untested code that is supposed to fix the problem, it
compiles and runs but does not work.

Can anyone suggest a solution (a working and tested code)?

Thanks
Yuval Naveh
Actimize
Israel

The code that was supposed to fix the problem:

[DllImport("comctl32.dll")]
static extern bool ImageList_Add( IntPtr hImageList, IntPtr hBitmap,
IntPtr hMask );
[DllImport("kernel32.dll")]
static extern bool RtlMoveMemory( IntPtr dest, IntPtr source, int
dwcount);
[DllImport("gdi32.dll")]
static extern IntPtr CreateDIBSection(IntPtr hdc, [In,
MarshalAs(UnmanagedType.LPStruct)] BITMAPINFO pbmi, uint iUsage, out IntPtr
ppvBits, IntPtr hSection, uint dwOffset);

[StructLayout(LayoutKind.Explicit)]
public class BITMAPINFO
{
[FieldOffset(0)]
public Int32 biSize;
[FieldOffset(4)]
public Int32 biWidth;
[FieldOffset(8)]
public Int32 biHeight;
[FieldOffset(12)]
public Int16 biPlanes;
[FieldOffset(14)]
public Int16 biBitCount;
[FieldOffset(16)]
public Int32 biCompression;
[FieldOffset(20)]
public Int32 biSizeImage;
[FieldOffset(24)]
public Int32 biXPelsPerMeter;
[FieldOffset(28)]
public Int32 biYPelsPerMeter;
[FieldOffset(32)]
public Int32 biClrUsed;
[FieldOffset(36)]
public Int32 biClrImportant;
[FieldOffset(40)]
public Int32 colors;
};

void AddPNGToImageList( ImageList il, string szFileName )
{
Bitmap bm = new Bitmap( szFileName );
IntPtr hBitmap, ppvBits;
BITMAPINFO bmi = new BITMAPINFO();

bmi.biSize = 40;
bmi.biBitCount = 32;
bmi.biPlanes = 1;
bmi.biWidth = bm.Width;
bmi.biHeight = bm.Height;
hBitmap = CreateDIBSection( new IntPtr(0), bmi, 0, out ppvBits, new
IntPtr(0), 0 );
BitmapData bitmapData;
Rectangle rect = new Rectangle(0, 0, bm.Width, bm.Height );
bitmapData = bm.LockBits( rect, ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb );
IntPtr pixels = bitmapData.Scan0;
RtlMoveMemory( ppvBits, pixels, bm.Height*bitmapData.Stride );
bm.UnlockBits( bitmapData );
ImageList_Add( il.Handle, hBitmap, new IntPtr(0) );
}
 
N

Neal Andrews

I have just had a look at the Listview control, and it handles my Images
with Alpha transparency fine.
Are you using Windows XP. Remember the use of the alpha channel in images is
only supported in WindowsXP and above, which is why as I said, you have to
call the EnableVisualStyles. I would also check that the alpha channel in
your ImageList has not been corrupted by drawing a test image directly from
the ImageList onto your form. If you still get the black areas then your
images in your ImageList have lost there alpha channel information.
Also the Images in the ImageList must be the same size as those displayed in
the ImageList i.e. 16x16 for small icons. If they are scaled then they will
not render correctly unless as I said you start handling the drawing of the
images your self as the ImageList control does not scale images with alpha
channel the ImageList control has a bug with scaling images (or as MS calls
it, a limitation:).....)

Regards
Neal


Yuval Naveh said:
Neal,
Thanks but your reply did not really help me.
My problem is that ImageList when connected to any control (ListView,
TreeView, ComboBox) will not show the image properly if the image as 256
levels in the alpha channel.
The alpha pixels become opaque.
I do not want to custom draw each element in each control, so Draw()
method will not do the trick.

Any other ideas?

Yuval

Neal Andrews said:
I have worked with the imagelist control but with the .net listview control.

The first thing is are you using a manifest
For the imagelist to support 32bpp images you need a manifest file or call
the following in .Net V1.1
Application.EnableVisualStyles
Application.DoEvents '(More Bug fixes)

If the images are still not displayed correctly then it maybe that the
images in the imagelist have lost there alpha channel (there are some bugs
with the imagelist control, where the images loose there alpha channel at
unexpected times when you add further images to the list.)

I have not used the ListView control yet so I cannot say how it is drawing
the images. When drawing 32bpp images from the imagelist control you must
use the Draw methods on the ImageList control and not the Draw Methods on
the Graphics object for the alpha channel to be drawn correctly. Another
problem with the ImageList control is that if you scale any images using the
draw methods on the imagelist control then the alpha channel info is also
lost. So you have to use the original win 32 api ImageList_DrawEx to draw
the scaled images from the imagelist control. I have submitted this as a bug
to MS, but as usual it's not a bug but a limitation (by design) of the
imagelist control, which means it is a bug but MS are not prepared to
fix
it
anytime soon.

Regards
Neal


Yuval Naveh said:
Hello,
I have encountered a problem while trying to display images in the
ListView control.
I am using Visual Studio 2003/C# on windows 2000 professional SP4.
My images are 32 bit PNG with alpha channel that has 256 levels.
After adding them to an ImageList component, and attaching the image list
to a list view, the images show thier alpha channel pixels as opaque pixels.
The problem seems to be with ImageList.
This subject has come up already in this newsgroup, and I saw no solution
for the problem.

Someone posted an untested code that is supposed to fix the problem, it
compiles and runs but does not work.

Can anyone suggest a solution (a working and tested code)?

Thanks
Yuval Naveh
Actimize
Israel

The code that was supposed to fix the problem:

[DllImport("comctl32.dll")]
static extern bool ImageList_Add( IntPtr hImageList, IntPtr hBitmap,
IntPtr hMask );
[DllImport("kernel32.dll")]
static extern bool RtlMoveMemory( IntPtr dest, IntPtr source, int
dwcount);
[DllImport("gdi32.dll")]
static extern IntPtr CreateDIBSection(IntPtr hdc, [In,
MarshalAs(UnmanagedType.LPStruct)] BITMAPINFO pbmi, uint iUsage, out IntPtr
ppvBits, IntPtr hSection, uint dwOffset);

[StructLayout(LayoutKind.Explicit)]
public class BITMAPINFO
{
[FieldOffset(0)]
public Int32 biSize;
[FieldOffset(4)]
public Int32 biWidth;
[FieldOffset(8)]
public Int32 biHeight;
[FieldOffset(12)]
public Int16 biPlanes;
[FieldOffset(14)]
public Int16 biBitCount;
[FieldOffset(16)]
public Int32 biCompression;
[FieldOffset(20)]
public Int32 biSizeImage;
[FieldOffset(24)]
public Int32 biXPelsPerMeter;
[FieldOffset(28)]
public Int32 biYPelsPerMeter;
[FieldOffset(32)]
public Int32 biClrUsed;
[FieldOffset(36)]
public Int32 biClrImportant;
[FieldOffset(40)]
public Int32 colors;
};

void AddPNGToImageList( ImageList il, string szFileName )
{
Bitmap bm = new Bitmap( szFileName );
IntPtr hBitmap, ppvBits;
BITMAPINFO bmi = new BITMAPINFO();

bmi.biSize = 40;
bmi.biBitCount = 32;
bmi.biPlanes = 1;
bmi.biWidth = bm.Width;
bmi.biHeight = bm.Height;
hBitmap = CreateDIBSection( new IntPtr(0), bmi, 0, out
ppvBits,
new
IntPtr(0), 0 );
BitmapData bitmapData;
Rectangle rect = new Rectangle(0, 0, bm.Width, bm.Height );
bitmapData = bm.LockBits( rect, ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb );
IntPtr pixels = bitmapData.Scan0;
RtlMoveMemory( ppvBits, pixels, bm.Height*bitmapData.Stride );
bm.UnlockBits( bitmapData );
ImageList_Add( il.Handle, hBitmap, new IntPtr(0) );
}
 

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