Archived

This topic is now archived and is closed to further replies.

Holy Fuzz

Managed DirectX LockRectangle Problem

Recommended Posts

Hey all. I'm having problems getting Texture.LockRectangle to work properly. I'm trying to scan the texture for any pixels with an alpha value < 255, and if one is found, set hasAlpha to true. My test BMP file has NO pixels with any alpha information, so hasAlpha should be set to false. However, the integer value of every single pixel I access is 0, which is certainly NOT the case. Here's the applicable code:
using System;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using D3D = Microsoft.DirectX.Direct3D;

/// <summary>

/// Win32 Direct3D implementation of IImage.

/// Used for storing a bitmap in video memory and drawing it to the screen.

/// </summary>

public class Win32D3DImage : IImage
{
	//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

	// VARIABLES -------------------------------------------------------


	private Texture texture;
	private bool hasAlpha;
	private Size size;

	//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

	// PUBLIC FUNCTIONS ------------------------------------------------


	/// <summary>

	/// Constructor.

	/// Loads the image from a file and puts it in video memory.

	/// </summary>

	/// <param name="filename">Name of file from which to load image.</param>

	/// <param name="dev">The device that owns the texture.</param>

	public Win32D3DImage(string filename, Device dev)
	{
		// Create image.

		texture = TextureLoader.FromFile(
			dev,
			filename,
			0,
			0,
			0,
			0,
			Format.X8B8G8R8,
			Pool.Managed,
			Filter.Triangle | Filter.Dither,
			Filter.Triangle | Filter.Dither,
			Color.Magenta.ToArgb());

		// Set size.

		size = new Size(
			texture.GetSurfaceLevel(0).Description.Width,
			texture.GetSurfaceLevel(0).Description.Height);

		// Scan for any alpha values.

		scanForAlpha();
	}

	//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

	// PRIVATE FUNCTIONS -----------------------------------------------


	/// <summary>

	/// Scans for any alpha values in the texture.

	/// </summary>

	private unsafe void scanForAlpha()
	{
		// There are no alpha values because we haven't found any yet.

		hasAlpha = false;

		// Lock texture.

		int pitch;
		GraphicsStream gs = texture.LockRectangle(0, LockFlags.ReadOnly, out pitch);
		int * ptr = (int *)gs.InternalData.ToPointer();

		// Loop through each pixel and check for non-255 alpha.

		for(int i = 0; i < size.Height; i++)
		{
			int * ptr2 = (int *)((byte *)ptr + pitch * i);
			for(int j = 0; j < size.Width; j++)
			{
				Color c = Color.FromArgb(*ptr2);
				if(c.A < 255)
				{
					hasAlpha = true;
					goto breakSpot;
				}

				ptr2++;
			}
		}
		breakSpot:

		System.Windows.Forms.MessageBox.Show(hasAlpha.ToString());

		// Unlock texture.

		//gs.Close();

		texture.UnlockRectangle(0);
	}
}
Note that: 1) The integer value of each pixel is always 0. 2) gs.InternalBuffer is always null, unlike gs.InternalData, which actually has a value. 3) gs.Length is 2147483647, which is definately NOT true. 4) The version of LockRectangle that returns an array doesn't work either -- each integer in the returned area is 0. Thanks for any help! - Fuzz [edited by - Holy Fuzz on April 4, 2004 12:33:37 AM]

Share this post


Link to post
Share on other sites
Well, that''s a little different from the way I''ve seen it done. What is the purpose of ptr2? I''m a bit confused about it.

This sample works for me. It goes through every color in a bitmap and sets it to white. As you can see, it''s very straightforward.



uint *pData = (uint*)texture.LockRectangle(0, LockFlags.None).InternalData.ToPointer();

for (int i=0; i < _size.Width; i++)
{
for (int j=0; j < _size.Height; j++)
{
*pData = (uint) Color.White.ToArgb();
pData++;
}
}


And here''s a safe version.


uint[,] data = (uint[,])texture.LockRectangle(0, LockFlags.None, _size.Width, _size.Height);


for (int i=0; i < _size.Width; i++)
{
for (int j=0; j < _size.Height; j++)
{
data[i,j] = (uint) Color.White.ToArgb();
}
}

Share this post


Link to post
Share on other sites
Okay, so here''s my new code, but it still doesn''t work; each int in the array is 0.


// Lock texture.

uint[,]pixels = (uint[,])texture.LockRectangle(typeof(uint), 0, LockFlags.ReadOnly, size.Width, size.Height);

// Loop through each pixel and check for non-255 alpha.

for(int i = 0; i < size.Width; i++)
{
for(int j = 0; j < size.Height; j++)
{
Color c = Color.FromArgb((int)pixels[i,j]);
if(c.A < 255)
{
hasAlpha = true;
goto breakSpot;
}
}
}
breakSpot:

// Unlock texture.

texture.UnlockRectangle(0);

Share this post


Link to post
Share on other sites
Okay, I got it to work. I accidently set my texture''s format to X8R8G8B8 instead of A8R8G8B8. I still don''t know why LockRectangle would return an array of zeros, but it works now.

Thanks!

Share this post


Link to post
Share on other sites