Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF TransformedBitmap/ScaleTransform中断alpha/全黑_C#_Wpf_Bitmap - Fatal编程技术网

C# WPF TransformedBitmap/ScaleTransform中断alpha/全黑

C# WPF TransformedBitmap/ScaleTransform中断alpha/全黑,c#,wpf,bitmap,C#,Wpf,Bitmap,我的后端代码使用alpha存储图像,以保持与尽可能多的格式的兼容性,但当我尝试调整大小并转换为JPG(无alpha)时,在没有设置alpha通道的地方,我得到了全黑 // Creation BitmapImage bmp = new BitmapImage(); bmp.BeginInit(); bmp.DecodePixelWidth = decodeWidth; bmp.DecodePixelHeight = decodeHeight; bmp.UriSource = new Uri(Fil

我的后端代码使用alpha存储图像,以保持与尽可能多的格式的兼容性,但当我尝试调整大小并转换为JPG(无alpha)时,在没有设置alpha通道的地方,我得到了全黑

// 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);
显然,所有这些代码都不在同一个函数中,但要点就在那里。 缩放后保存
FormatConvertedBitmap
时,原始位图中指定alpha的位置为黑色。 在缩放之前,它按预期工作。没有黑色

比较 (由于链接限制而删除)

您可以从上面的图像中看到,大多数原始图像都有一个alpha通道,该通道会转换为黑色,但只有在转换之后

我找到了这个 我的问题与此类似,只是这不仅仅是空白背景。在这黑暗中有细节

TLDR变换/缩放似乎破坏了在WPF中更改像素格式的能力。
我想要什么:非黑色图像。alpha下面的RGB肯定不是黑色的。
我得到的:黑色图像,阿尔法通道对结果有一定影响。
原因:据我所知,这是由于重新调整了大小。
是我做错了什么,还是这是个奇怪的错误

原始dds

测试项目
这个项目充分说明了我的处境。
它需要Windows 8.1+(用于dds编解码器)和.NET 4.6

思考/测试过程
我想我将为我如何进入这一阶段添加一些背景。
1.写了一个dds友好的图像转换器(其实这个工具的初衷) 2.发现带有alpha通道的dds在使用JpegBitmapEncoder类转换为jpg时变为黑色。
3.根据图案判断这是阿尔法问题。
4.通过在不同点保存图像进行调试,结果显示图像在调整大小之前是良好的。
5.在调整大小之前,另存为jpg是有效的。没有黑色。
6.调整大小后,jpg在alpha=0的所有区域均为黑色。
7.认为编码器对alpha进行了预乘,结果像素为黑色。
8.无法理解为什么缩放会产生这样的效果,但尝试通过转换为Bgr32来剥离alpha。

9缩放后转换时仍为黑色

我不喜欢将此作为一个答案,因为它更多地是一个解决方法,而不是修复为什么缩放不能保留alpha

但这是我的解决办法。表现出奇地好。
1)拉出alpha通道。
2)使用alpha值作为所有rgb通道(即rgb=alpha)构建新位图,以使生成的图像为灰度。
3)将原始图像的颜色空间从ARGB更改为RGB。由于alpha已删除,因此不会破坏任何内容。
4)缩放两幅图像(原始RGB和原始alpha)。
5)将缩放后的RGB颜色空间更改回ARGB(同样,这不会真正改变任何内容)。
6)将缩放的alpha合并到缩放的RGB(现在为ARGB)位图中

WriteableBitmap bmp = mipMap.BaseImage;
int origWidth = bmp.PixelWidth;
int origHeight = bmp.PixelHeight;
int origStride = origWidth * 4;
int newWidth = (int)(origWidth * scale);
int newHeight = (int)(origHeight * scale);
int newStride = newWidth * 4;



// Pull out alpha since scaling with alpha doesn't work properly for some reason
WriteableBitmap alpha = new WriteableBitmap(origWidth, origHeight, 96, 96, PixelFormats.Bgr32, null);
unsafe
{
    int index = 3;
    byte* alphaPtr = (byte*)alpha.BackBuffer.ToPointer();
    byte* mainPtr = (byte*)bmp.BackBuffer.ToPointer();
    for(int i = 0; i < origWidth * origHeight * 3; i += 4)
    {
        // Set all pixels in alpha to value of alpha from original image - otherwise scaling will interpolate colours
        alphaPtr[i] = mainPtr[index];
        alphaPtr[i+1] = mainPtr[index];
        alphaPtr[i+2] = mainPtr[index];
        alphaPtr[i+3] = mainPtr[index];
        index += 4;
    }
}

FormatConvertedBitmap main = new FormatConvertedBitmap(bmp, PixelFormats.Bgr32, null, 0);

// Scale RGB and alpha
ScaleTransform scaletransform = new ScaleTransform(scale, scale);
TransformedBitmap scaledMain = new TransformedBitmap(main, scaletransform);
TransformedBitmap scaledAlpha = new TransformedBitmap(alpha, scaletransform);

// Put alpha back in
FormatConvertedBitmap newConv = new FormatConvertedBitmap(scaledMain, PixelFormats.Bgra32, null, 0);
WriteableBitmap resized = new WriteableBitmap(newConv);
WriteableBitmap newAlpha = new WriteableBitmap(scaledAlpha);
unsafe
{
    byte* resizedPtr = (byte*)resized.BackBuffer.ToPointer();
    byte* alphaPtr = (byte*)newAlpha.BackBuffer.ToPointer();
    for (int i = 3; i < newStride; i += 4)
        resizedPtr[i] = alphaPtr[i];
}
WriteableBitmap bmp=mipMap.BaseImage;
int origWidth=bmp.PixelWidth;
int origHeight=bmp.PixelHeight;
int origStride=origWidth*4;
int newWidth=(int)(初始宽度*刻度);
int新高度=(int)(origHeight*比例);
int newStride=newWidth*4;
//拉出alpha,因为由于某些原因,使用alpha进行缩放无法正常工作
WriteableBitmap alpha=新的WriteableBitmap(origWidth,origHeight,96,96,PixelFormats.Bgr32,null);
不安全的
{
int指数=3;
字节*alphaPtr=(字节*)alpha.BackBuffer.ToPointer();
字节*mainPtr=(字节*)bmp.BackBuffer.ToPointer();
对于(int i=0;i

似乎表现不错,但更重要的是,它能满足我的需要。我不喜欢将此作为一个答案,因为它更像是一个解决办法,而不是修复为什么缩放不能保留alpha

但这是我的解决办法。表现出奇地好。
1)拉出alpha通道。
2)使用alpha值作为所有rgb通道(即rgb=alpha)构建新位图,以使生成的图像为灰度。
3)将原始图像的颜色空间从ARGB更改为RGB。由于alpha已删除,因此不会破坏任何内容。
4)缩放两幅图像(原始RGB和原始alpha)。
5)将缩放后的RGB颜色空间更改回ARGB(同样,这不会真正改变任何内容)。
6)将缩放的alpha合并到缩放的RGB(现在为ARGB)位图中

WriteableBitmap bmp = mipMap.BaseImage;
int origWidth = bmp.PixelWidth;
int origHeight = bmp.PixelHeight;
int origStride = origWidth * 4;
int newWidth = (int)(origWidth * scale);
int newHeight = (int)(origHeight * scale);
int newStride = newWidth * 4;



// Pull out alpha since scaling with alpha doesn't work properly for some reason
WriteableBitmap alpha = new WriteableBitmap(origWidth, origHeight, 96, 96, PixelFormats.Bgr32, null);
unsafe
{
    int index = 3;
    byte* alphaPtr = (byte*)alpha.BackBuffer.ToPointer();
    byte* mainPtr = (byte*)bmp.BackBuffer.ToPointer();
    for(int i = 0; i < origWidth * origHeight * 3; i += 4)
    {
        // Set all pixels in alpha to value of alpha from original image - otherwise scaling will interpolate colours
        alphaPtr[i] = mainPtr[index];
        alphaPtr[i+1] = mainPtr[index];
        alphaPtr[i+2] = mainPtr[index];
        alphaPtr[i+3] = mainPtr[index];
        index += 4;
    }
}

FormatConvertedBitmap main = new FormatConvertedBitmap(bmp, PixelFormats.Bgr32, null, 0);

// Scale RGB and alpha
ScaleTransform scaletransform = new ScaleTransform(scale, scale);
TransformedBitmap scaledMain = new TransformedBitmap(main, scaletransform);
TransformedBitmap scaledAlpha = new TransformedBitmap(alpha, scaletransform);

// Put alpha back in
FormatConvertedBitmap newConv = new FormatConvertedBitmap(scaledMain, PixelFormats.Bgra32, null, 0);
WriteableBitmap resized = new WriteableBitmap(newConv);
WriteableBitmap newAlpha = new WriteableBitmap(scaledAlpha);
unsafe
{
    byte* resizedPtr = (byte*)resized.BackBuffer.ToPointer();
    byte* alphaPtr = (byte*)newAlpha.BackBuffer.ToPointer();
    for (int i = 3; i < newStride; i += 4)
        resizedPtr[i] = alphaPtr[i];
}
WriteableBitmap bmp=mipMap.BaseImage;
int origWidth=bmp.PixelWidth;
int origHeight=bmp.PixelHeight;
int origStride=origWidth*4;
int newWidth=(int)(初始宽度*刻度);
int新高度=(int)(origHeight*比例);
在里面