从 SharpDX 位图转换为 GorgonImage 失败
Fail in converting from SharpDX bitmap to GorgonImage
我在我的项目中使用 Gorgon 2D 库(基于 SharpDX 构建)。我在从 SharpDX 位图转换为 GorgonImage 时遇到问题。我post我的问题在这里,希望你们能帮助我解决它。谢谢
我使用此代码创建 SharpDX 位图:
private GorgonImage D2DBitmapToGorgonImage(this SharpDX.Direct2D1.Bitmap1 bm, SharpDX.Direct2D1.DeviceContext5 D2D1Context5)
{
SharpDX.DataRectangle map;
if (bm.Options == SharpDX.Direct2D1.BitmapOptions.Target)
{
var img1 = new SharpDX.Direct2D1.Bitmap1(D2D1Context5, new SharpDX.Size2(bm.PixelSize.Width, bm.PixelSize.Height), new SharpDX.Direct2D1.BitmapProperties1()
{
PixelFormat = new SharpDX.Direct2D1.PixelFormat(DXGI.Format.R8G8B8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied),
DpiX = 96,
DpiY = 96,
BitmapOptions = SharpDX.Direct2D1.BitmapOptions.CannotDraw | SharpDX.Direct2D1.BitmapOptions.CpuRead
});
img1.CopyFromBitmap(bm, new SharpDX.Mathematics.Interop.RawPoint(0, 0), new SharpDX.Mathematics.Interop.RawRectangle(0, 0, bm.PixelSize.Width, bm.PixelSize.Height));
map = img1.Map(SharpDX.Direct2D1.MapOptions.Read);
img1.Unmap();
img1.Dispose();
}
else if (bm.Options == (SharpDX.Direct2D1.BitmapOptions.CannotDraw | SharpDX.Direct2D1.BitmapOptions.CpuRead))
map = bm.Map(SharpDX.Direct2D1.MapOptions.Read);
else
throw new Exception("Can not convert from Direc2D1.Bitmap1 to GorgonImage");
var size = bm.PixelSize.Width * bm.PixelSize.Height * 4;
byte[] bytes = new byte[size];
Marshal.Copy(map.DataPointer, bytes, 0, size);
IGorgonImageInfo info = new GorgonImageInfo(ImageType.Image2D, BufferFormat.R8G8B8A8_UNorm)
{
Width = bm.PixelSize.Width,
Height = bm.PixelSize.Height,
};
GorgonImage nqi = new GorgonImage(info);
unsafe
{
for (int y = 0; y < info.Height; y++)
{
// We only need the width here, as our pointer will handle the stride by virtue of being an int.
//int* offset = pixels + (y * bitmapLock.Width);
int destOffset = y * nqi.Buffers[0].PitchInformation.RowPitch;
for (int x = 0; x < info.Width; x++)
{
var position = (y * info.Width + x) * 4;
byte r = 0, g = 0, b = 0, alpha = bytes[position + 3];
if(bm.PixelFormat.AlphaMode == SharpDX.Direct2D1.AlphaMode.Premultiplied)
{
if (alpha != 0)
{
var div_alpha = 0xff00 / alpha;
r = (byte)((bytes[position] * div_alpha + 0x80) >> 8);
g = (byte)((bytes[position + 1] * div_alpha + 0x80) >> 8);
b = (byte)((bytes[position + 2] * div_alpha + 0x80) >> 8);
}
}
else
{
r = bytes[position+1];
g = bytes[position+2];
b = bytes[position+3];
}
SharpDX.Color4 cl4 = new SharpDX.Color4((float)r/255.0f, (float)g/255.0f, (float)b/255.0f, (float)alpha/255.0f);
// The DXGI format nomenclature is a little confusing as we tend to think of the layout as being highest to
// lowest, but in fact, it is lowest to highest.
// So, we must convert to ABGR even though the DXGI format is RGBA. The memory layout is from lowest
// (R at byte 0) to the highest byte (A at byte 3).
// Thus, R is the lowest byte, and A is the highest: A(24), B(16), G(8), R(0).
int* destBuffer = (int*)(Unsafe.AsPointer(ref nqi.Buffers[0].Data[destOffset]));
*destBuffer = cl4.ToRgba(); //color.ToABGR();
//offset++;
destOffset += 4;
}
}
}
return nqi;
}
问题是,SharpDX 位图的大小为 (1280,720)。转换后的图像正常:
但使用大小为 (1281,720) 的 SharpDX 位图。转换功能无法正常工作。我得到了这个转换后的图像:
我找不到我的代码有什么问题。你们能帮我指出问题吗?谢谢
这些是我使用的 Gorgon 类型:
GorgonImage
GorgonImageInfo
GorgonImageBuffer
GorgonNativeBuffer
这种带有环绕的倾斜通常是步幅与宽度的问题。您可以使用倾斜的方向(结合行顺序,通常是自上而下但并非总是如此)来查看它是源地址计算中的问题还是目标地址计算中的问题。这里倾斜的角度为 "backwards",这意味着 src 地址前进得太慢,结果像素与它们应该在的位置相比越来越向右和向下。原则上,相同的效果可能是由目标地址前进太快引起的,但这不太可能(步幅与宽度问题不会这样做,使用 错误的 步幅可能)
所以 position
是错误的,并且 (y * info.Width + x) * 4
使用宽度而不是可疑的步幅。
源步长是 map.Pitch
所以 position
应该是 y * map.Pitch + 4 * x
我在我的项目中使用 Gorgon 2D 库(基于 SharpDX 构建)。我在从 SharpDX 位图转换为 GorgonImage 时遇到问题。我post我的问题在这里,希望你们能帮助我解决它。谢谢
我使用此代码创建 SharpDX 位图:
private GorgonImage D2DBitmapToGorgonImage(this SharpDX.Direct2D1.Bitmap1 bm, SharpDX.Direct2D1.DeviceContext5 D2D1Context5)
{
SharpDX.DataRectangle map;
if (bm.Options == SharpDX.Direct2D1.BitmapOptions.Target)
{
var img1 = new SharpDX.Direct2D1.Bitmap1(D2D1Context5, new SharpDX.Size2(bm.PixelSize.Width, bm.PixelSize.Height), new SharpDX.Direct2D1.BitmapProperties1()
{
PixelFormat = new SharpDX.Direct2D1.PixelFormat(DXGI.Format.R8G8B8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied),
DpiX = 96,
DpiY = 96,
BitmapOptions = SharpDX.Direct2D1.BitmapOptions.CannotDraw | SharpDX.Direct2D1.BitmapOptions.CpuRead
});
img1.CopyFromBitmap(bm, new SharpDX.Mathematics.Interop.RawPoint(0, 0), new SharpDX.Mathematics.Interop.RawRectangle(0, 0, bm.PixelSize.Width, bm.PixelSize.Height));
map = img1.Map(SharpDX.Direct2D1.MapOptions.Read);
img1.Unmap();
img1.Dispose();
}
else if (bm.Options == (SharpDX.Direct2D1.BitmapOptions.CannotDraw | SharpDX.Direct2D1.BitmapOptions.CpuRead))
map = bm.Map(SharpDX.Direct2D1.MapOptions.Read);
else
throw new Exception("Can not convert from Direc2D1.Bitmap1 to GorgonImage");
var size = bm.PixelSize.Width * bm.PixelSize.Height * 4;
byte[] bytes = new byte[size];
Marshal.Copy(map.DataPointer, bytes, 0, size);
IGorgonImageInfo info = new GorgonImageInfo(ImageType.Image2D, BufferFormat.R8G8B8A8_UNorm)
{
Width = bm.PixelSize.Width,
Height = bm.PixelSize.Height,
};
GorgonImage nqi = new GorgonImage(info);
unsafe
{
for (int y = 0; y < info.Height; y++)
{
// We only need the width here, as our pointer will handle the stride by virtue of being an int.
//int* offset = pixels + (y * bitmapLock.Width);
int destOffset = y * nqi.Buffers[0].PitchInformation.RowPitch;
for (int x = 0; x < info.Width; x++)
{
var position = (y * info.Width + x) * 4;
byte r = 0, g = 0, b = 0, alpha = bytes[position + 3];
if(bm.PixelFormat.AlphaMode == SharpDX.Direct2D1.AlphaMode.Premultiplied)
{
if (alpha != 0)
{
var div_alpha = 0xff00 / alpha;
r = (byte)((bytes[position] * div_alpha + 0x80) >> 8);
g = (byte)((bytes[position + 1] * div_alpha + 0x80) >> 8);
b = (byte)((bytes[position + 2] * div_alpha + 0x80) >> 8);
}
}
else
{
r = bytes[position+1];
g = bytes[position+2];
b = bytes[position+3];
}
SharpDX.Color4 cl4 = new SharpDX.Color4((float)r/255.0f, (float)g/255.0f, (float)b/255.0f, (float)alpha/255.0f);
// The DXGI format nomenclature is a little confusing as we tend to think of the layout as being highest to
// lowest, but in fact, it is lowest to highest.
// So, we must convert to ABGR even though the DXGI format is RGBA. The memory layout is from lowest
// (R at byte 0) to the highest byte (A at byte 3).
// Thus, R is the lowest byte, and A is the highest: A(24), B(16), G(8), R(0).
int* destBuffer = (int*)(Unsafe.AsPointer(ref nqi.Buffers[0].Data[destOffset]));
*destBuffer = cl4.ToRgba(); //color.ToABGR();
//offset++;
destOffset += 4;
}
}
}
return nqi;
}
问题是,SharpDX 位图的大小为 (1280,720)。转换后的图像正常:
但使用大小为 (1281,720) 的 SharpDX 位图。转换功能无法正常工作。我得到了这个转换后的图像:
我找不到我的代码有什么问题。你们能帮我指出问题吗?谢谢
这些是我使用的 Gorgon 类型:
GorgonImage
GorgonImageInfo
GorgonImageBuffer
GorgonNativeBuffer
这种带有环绕的倾斜通常是步幅与宽度的问题。您可以使用倾斜的方向(结合行顺序,通常是自上而下但并非总是如此)来查看它是源地址计算中的问题还是目标地址计算中的问题。这里倾斜的角度为 "backwards",这意味着 src 地址前进得太慢,结果像素与它们应该在的位置相比越来越向右和向下。原则上,相同的效果可能是由目标地址前进太快引起的,但这不太可能(步幅与宽度问题不会这样做,使用 错误的 步幅可能)
所以 position
是错误的,并且 (y * info.Width + x) * 4
使用宽度而不是可疑的步幅。
源步长是 map.Pitch
所以 position
应该是 y * map.Pitch + 4 * x