1
votes

I am working with an old game format and they used indexed bitmaps. For some materials with transparency, they use the first index in the palette as the value that is set to invisible. In code, I clone the bitmap, set this palette value to be fully transparent and then export it as a PNG. It works perfectly on Windows. But on Mac, it does not.

Here is what I do:

Bitmap cloneBitmap;
cloneBitmap = image.Clone(new Rectangle(0, 0, image.Width, image.Height), PixelFormat.Format8bppIndexed);

var palette = cloneBitmap.Palette;
palette.Entries[0] = Color.FromArgb(0, 0, 0, 0);
cloneBitmap.Palette = palette;

cloneBitmap.Save(filePath + fileName, ImageFormat.Png);

This works just fine on PC. The image is output with transparency. On Mac, it does not have transparency, the pixels with this index are just black.

2
Have you tried with 0,255,255,255 instead: docs.microsoft.com/en-us/dotnet/api/…Simon Mourier
@SimonMourier This makes the pixels that should be transparent white instead of black. It had no effect on saving the transparency.Satchmo Brown
Is it .NET Core? Or Mono? Or what?picolino

2 Answers

2
votes

I assume you are using standard System.Drawing library for image processing in your application. There are a lot of features in this library are a thin wrappers around Windows GDI+ API. So macOS may not have some functions for processing images.

So you have these options to handle this issue:

Install GDI+ library on your Mac

If you use mono, you can try to install GDI+ libs to provide GDI+ api for System.Drawing (source).

brew install mono-libgdiplus

Use Windows Compatibility Pack

Windows Compatibility Pack provides API, used by .NET Framework in Windows only, for cross-platform applications, written on .NET Core/Standard.

See docs for details.

However, Microsoft.Windows.Compatibility package includes many, many Windows related APIs that you probably doesn't need at all. If that, you can install only System.Drawing.Common package. This package is part of compitability pack for System.Drawing functions.

See helpful article about how to use System.Drawing.Common in .NET Core.

Use another third party library

If previous solutions does not help with your issue, try to use third party open-source libraries to acomplish your task. They definately will work correctly on macOS.

See this useful article from Microsoft blog to find image processing library for your purposes.

1
votes

Requirements

  • Input: 256-color palette (8bpp) BMP
  • Output: PNG with transparency, the areas in the input image that use the first entry of the accociated palette must be displayed transparently
  • OS: macOS and Windows

Verification

  • To have a test case, I created a 256-color palette (8bpp) BMP with different colors
  • in the middle of the BMP there is a rectangular area that uses the color with index 0
  • to ensure that the area in the middle is transparent, I opened the resulting .png in an image editing software that displays transparent areas with a checkerboard pattern

Original Code

When testing with original code shown in question it gives the following results:

  • Windows .NET Framework: area in middle is transparent
  • Windows .NET Core: area in middle is transparent
  • macOS .NET Core: area in middle is black
  • macOS Mono: area in middle is black

This was to be expected, as the OP also noted this in the question.

Workaround

One way that works in all 4 environments (Windows .NET Framework, .NET Core Windows/Mac and Mono) is to call the MakeTransparent method with the color of the first entry.

Documentation says:

public void MakeTransparent (System.Drawing.Color transparentColor);

Makes the specified color transparent for this Bitmap.

see https://docs.microsoft.com/en-us/dotnet/api/system.drawing.bitmap.maketransparent?view=netcore-3.1#System_Drawing_Bitmap_MakeTransparent_System_Drawing_Color_

In code it would look like this:

var firstColor = image.Palette.Entries[0];
image.MakeTransparent(Color.FromArgb(0, firstColor.R, firstColor.G, firstColor.B));
image.Save(filePath + fileName, ImageFormat.Png);

If the first color may also appear in other entries of the palette, you may need to make sure that the color in the first entry of the source palette is unique to prevent other areas from becoming transparent as well.

Test

If one opens the resulting PNG in an image editing program, one can see the transparent area in the middle of the image:

resulting PNG in imaging software