Reputation: 25927
I'm preparing icons for my application. My application utilizes the system Ribbon and I need to prepare proper XML file with its description. In this file I'm providing images I want to be displayed on specific items.
On Windows 8 I may simply use .png images with alpha channel and they are interpreted correctly. Unfortunately, under Windows 7 only specially prepared BMPs work correctly. But I have simply no idea on how to create such BMPs.
This is an example of image, which actually works and is being displayed on the Ribbon - it comes from Samples folder of the control I'm using (RibbonLib).
(You may download the original "magic" BMP here)
As you see (mostly probably), even the browser has trouble displaying it, though on the Ribbon it looks OK:
Now, if I only open this image in Gimp and then save to disk without modifications, it displays correctly in the Windows Explorer (and, mostly likely, in browser), but no longer on the Ribbon:
I fail to see, what is so "magic" with this bitmap. Thus, I have no idea on how should I prepare my own images to be displayed correctly on the Ribbon and which tool should I use to save that "magic" BMP.
Upvotes: 0
Views: 304
Reputation: 25927
Mystery solved. Bitmaps for Win32 Ribbon has to be in PixelFormat.Format32bppRgb
(notice: RGB, not ARGB). This format is supposed to hold XRGB data, where X is ignored. Apparently Ribbon does not ignore it, instead uses as a binary alpha channel. The transparent color must be XRGB (0, 0, 0, 0).
Here's a small console tool to convert PNG image to compatible BMP:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace BmpConverter
{
class Program
{
static void Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("Usage:");
Console.WriteLine("");
Console.WriteLine("BmpConverter file.png");
Console.WriteLine();
return;
}
string filename = args[0];
if (!File.Exists(filename))
{
Console.WriteLine("Error: file does not exist!");
Console.WriteLine();
return;
}
if (Path.GetExtension(filename).ToUpper() != ".PNG")
{
Console.WriteLine("Error: Only PNG files are supported!");
Console.WriteLine();
return;
}
string resultFilename;
if (args.Length > 1 && args[1] != null)
resultFilename = args[1];
else
resultFilename = Path.ChangeExtension(filename, ".BMP");
Bitmap source = new Bitmap(filename);
Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format32bppRgb);
for (int y = 0; y < source.Height; y++)
{
byte[] sourceLine, destLine;
var sourceData = source.LockBits(new Rectangle(0, y, source.Width, 1), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
var destData = destination.LockBits(new Rectangle(0, y, source.Width, 1), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
sourceLine = new byte[sourceData.Stride];
Marshal.Copy(sourceData.Scan0, sourceLine, 0, sourceData.Stride);
destLine = new byte[sourceLine.Length];
for (int x = 0; x < source.Width; x++)
{
bool transparent = sourceLine[x * 4 + 3] < 128;
destLine[x * 4] = transparent ? (byte)0 : sourceLine[x * 4];
destLine[x * 4 + 1] = transparent ? (byte)0 : sourceLine[x * 4 + 1];
destLine[x * 4 + 2] = transparent ? (byte)0 : sourceLine[x * 4 + 2];
destLine[x * 4 + 3] = transparent ? (byte)0 : (byte)255;
}
Marshal.Copy(destLine, 0, destData.Scan0, source.Width * 4);
source.UnlockBits(sourceData);
destination.UnlockBits(destData);
}
destination.Save(resultFilename, ImageFormat.Bmp);
}
}
}
Upvotes: 2