Jump to content
  • Advertisement
Sign in to follow this  

[SlimDX] datarectangle RGB array of bytes

This topic is 3454 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi I need to convert an array of R8G8B8 color in a Texture2D. I can't get it right. I need the fastest possible way to convert this array of bytes to a texture, since the bytes are spawned by videocapture and I'm rendering this live on whatever object. Maybe somebody else sees what I'm doing wrong. thanks Alexander public static Texture2D CreateTexture2DFromRGB(IntPtr aBuffer, int aBufferSize, int aWidth, int aHeight) { if (aBufferSize <= 0) return null; unsafe { Texture2DDescription d = new Texture2DDescription(); d.ArraySize = 1; d.BindFlags = BindFlags.ShaderResource; d.CpuAccessFlags = CpuAccessFlags.Write; d.Format = SlimDX.DXGI.Format.R8G8B8A8_UNorm; d.Height = aHeight; d.MipLevels = 1; d.OptionFlags = ResourceOptionFlags.None; d.Usage = ResourceUsage.Dynamic; d.Width = aWidth; d.SampleDescription = new SlimDX.DXGI.SampleDescription(1, 0); Texture2D t = new Texture2D(aDevice, d); DataRectangle map = t.Map(0, MapMode.WriteDiscard, MapFlags.None); map.Data.Seek(0, System.IO.SeekOrigin.Begin); byte* p = (byte*)(void*)aBuffer; for( int row = 0; row < aHeight; row++){ int rowStart = row * map.Pitch; map.Data.Seek(rowStart, System.IO.SeekOrigin.Begin); for (int col = 0; col < aWidth; col++) { map.Data.WriteByte(p[0]); map.Data.WriteByte(p[1]); map.Data.WriteByte(p[2]); map.Data.WriteByte(0xFF); p += 3; } } t.Unmap(1); return t; } } }

Share this post

Link to post
Share on other sites
Using the unsafe keyword is icky.

SlimDX's DataStream has a WriteRange overload that can take an IntPtr. You can probably use that -- you'll still have to account for row padding via the pitch and such, unles the data in your IntPtr happens to match exactly, but will avoid the unsafe and some of the loop overhead.

What about this code you posted doesn't work right? Or does it work but just run slowly? The WriteRange IntPtr overload will likely be faster, although upon closer examination you won't be able to use it if you have to pad out the data like you seem to be doing with the write of the 0xFF byte.

Share this post

Link to post
Share on other sites

This method isn't giving any errors, but it is causing the present method to crash. So I assume I'm writing bogus information to the texture.

But the real problem with al this is that I can't find anywhere the "underlaying" structure this texture is using. For ex... a bitmap has an easy structure, so it is easy to perform optimzations when loading data or to mimic a stream as a bitmap.

I was thinking to create a "bitmap 32 look alike structure" in a datastream and just call the Texture.FromStream method. I know this involves an "extra" step of copying and formatting memory, but it will make it easier.

I don't really need to xFF byte, it is just my alpha channel. I can't find a texture in RGB format.



Share this post

Link to post
Share on other sites

The combination of WriteRange and a simple bitmap header works excellent for an RG inputstream to a texture. For the completeness, I have included the source

use it like this
using (DataStream str = HDx.Core.Helpers.Bitmap.CreateRGBBitmapStream(aBuffer, aBufferSize, aWidth, aHeight)) {
return Texture2D.FromStream(HDx.Core.Application.Current.Device, str, (int)str.Length, LargeILI(false));

routine to make a valid bmpstream to prevent unsafe magic

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace HDx.Core.Helpers {

public class Bitmap {

[StructLayout(LayoutKind.Explicit, Size = 14)]
private struct tagBITMAPFILEHEADER {
public Int16 bfType;
public Int32 bfSize;
public Int16 bfReserved1;
public Int16 bfReserved2;
public Int32 bfOffBits;

public static int Size = 14;
public tagBITMAPFILEHEADER(int aSize) {
bfType = 19778;
bfOffBits = 54;
bfReserved1 = 0;
bfReserved2 = 0;
bfSize = aSize;

[StructLayout(LayoutKind.Explicit, Size = 40)]
private struct tagBITMAPINFOHEADER {
Int32 biSize;
Int32 biWidth;
Int32 biHeight;
Int16 biPlanes;
Int16 biBitCount;
Int32 biCompression;
Int32 biSizeImage;
Int32 biXPelsPerMeter;
Int32 biYPelsPerMeter;
Int32 biClrUsed;
Int32 biClrImportant;

public tagBITMAPINFOHEADER(int aWidth, int aHeight, int aBitCount) {
biSize = 40;
biWidth = aWidth;
biHeight = aHeight;
biPlanes = 1;
biBitCount = (Int16)aBitCount;
biCompression = 0;
biSizeImage = 0;
biXPelsPerMeter = 0;
biYPelsPerMeter = 0;
biClrUsed = 0;
biClrImportant = 0;
public static int Size = 40;

public static int CalcBitmapFileSize(int aWidth, int aHeight, int aBitCount) {
return CalcBitmapDataSize(aWidth, aHeight, aBitCount) + tagBITMAPFILEHEADER.Size + tagBITMAPINFOHEADER.Size;

public static int CalcBitmapDataSize(int aWidth, int aHeight, int aBitCount) {
return aWidth * aHeight * (aBitCount / 8);

public static void WriteBitmapHeader(SlimDX.DataStream aStream, int aWidth, int aHeight, int aBitCount) {

private static IntPtr Offset(IntPtr src, int offset) {
switch (IntPtr.Size) {
case 4:
return new IntPtr(src.ToInt32() + offset);
case 8:
return new IntPtr(src.ToInt64() + offset);
throw new NotSupportedException("Surprise! This is running on a machine where pointers are " + IntPtr.Size + " bytes and arithmetic doesn't work in C# on them.");

/// <summary>
/// Creates a 24 bit bitmap
/// Videocog output
/// </summary>
public static SlimDX.DataStream CreateRGBBitmapStream(IntPtr aBuffer, int aBufferSize, int aWidth, int aHeight) {
int FileSize = CalcBitmapFileSize(aWidth, aHeight, 24);
SlimDX.DataStream Stream = new SlimDX.DataStream(FileSize, true, true);

Stream.Write<tagBITMAPINFOHEADER>(new tagBITMAPINFOHEADER(aWidth, aHeight, 24));

int PadBytes = (aWidth * 3) % 4;
if (PadBytes == 0) {
Stream.WriteRange(aBuffer, aBufferSize);
} else {
byte[] pad = new byte[PadBytes];
IntPtr b = aBuffer;
int BytesPerRow = aWidth * 3;
for (int r = 0; r < aHeight; r++){
Stream.WriteRange(b, BytesPerRow);
Stream.Seek(0, System.IO.SeekOrigin.Begin);
return Stream;

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!