My backend code stores images with alpha to maintain compatibility with as many formats as possible, but when I try to resize and convert to JPG (no alpha), I get all black where the alpha channel wasn't set.
// Creation
BitmapImage bmp = new BitmapImage();
bmp.BeginInit();
bmp.DecodePixelWidth = decodeWidth;
bmp.DecodePixelHeight = decodeHeight;
bmp.UriSource = new Uri(Filename);
bmp.CacheOption = BitmapCacheOption.OnLoad;
bmp.EndInit();
bmp.Freeze();
// Scaling
var scalar = new ScaleTransform(scale, scale);
var bmp = new TransformedBitmap(img, scalar);
bmp.Freeze();
// Testing
var formatted = new FormatConvertedBitmap(bmp, PixelFormats.Bgr32, null, 0);
PngBitmapEncoder png = new PngBitmapEncoder();
MemoryStream ms = new MemoryStream();
png.Frames.Add(BitmapFrame.Create(formatted);
png.Save(ms);
File.WriteAllBytes(dest, ms);
Clearly all that code isn't in the same function, but the gist is there.
When the FormatConvertedBitmap
is saved AFTER SCALING, it's black where there's alpha specified in the original bitmap.
Before scaling, it works as expected. No blackness.
Comparison (removed due to link restrictions)
You can see from the image above that most of the original has an alpha channel, which gets converted to black but ONLY after the transformation.
I found this Saving Windows.Media.Drawing with BmpBitmapEncoder black image - how to remove alpha? and my problem is similar, except that this isn't just blank backgrounds. There's detail "under" this blackness.
TLDR transforming/scaling seems to break the ability to change pixel formats in WPF.
What I want: Non black image. The RGB underneath the alpha definitely isn't black.
What I got: Black image where alpha channel had some influence on the outcome.
Cause: As far as I can tell, it's due to re-sizing.
Am I doing something wrong, or is this some weird bug?
Original dds
https://dl.dropboxusercontent.com/u/37301843/MASSEFFECT3.EXE_0xCFC054A8%20No%20MIPS.dds
TEST PROJECT
https://dl.dropboxusercontent.com/u/37301843/StackOverflowExample.7z
This project fully demonstrates my situation.
It requires Windows 8.1+ (for dds codecs) and .NET 4.6.
Thought/testing process
I figure I'll add some context to how I got to this stage.
1. Wrote a dds friendly image converter (original purpose of this tool actually)
2. Discovered that dds' with alpha channels turned out black when converted to jpg using the JpegBitmapEncoder class.
3. Figured by the patterning that it was an alpha problem.
4. Debugging via saving image at various points showed the image was fine until it was resized.
5. Before resizing, saving as jpg works. No blackness.
6. After resizing, jpg is black in all areas where alpha = 0.
7. Figured the encoder was premultiplying alpha such that the resulting pixels were black.
8. Couldn't work out why scaling would do such a thing, but tried stripping out the alpha by converting to Bgr32.
9. Still black when converting after scaling.