Wrong value in getting pixel value from SharpDX.Diret2D1.Bitmap1

Started by
10 comments, last by hoahong 4 years, 8 months ago

Hi guys,

I created a Bitmap1 and filled it with RawColor4(1f, 0.0f, 0.0f, 0.5f) by this code:


 D2D1.Bitmap1 img = new D2D1.Bitmap1(_graphics.D2D1Context5, new SharpDX.Size2(640, 480), new BitmapProperties1()
  					 {
                        PixelFormat = new D2D1.PixelFormat(Format.R8G8B8A8_UNorm, D2D1.AlphaMode.Premultiplied),
                        DpiX = 96,
                        DpiY = 96,
                        BitmapOptions = BitmapOptions.Target
                    });

_graphics.D2D1Context5.Target = img;
_graphics.D2D1Context5.BeginDraw();
_graphics.D2D1Context5.AntialiasMode = AntialiasMode.Aliased;

//RawColor4 with Red=1f; G=0.0f; B=0.0f; Alpha = 0.5f;
SolidColorBrush br = new SolidColorBrush(_graphics.D2D1Context5, new SharpDX.Mathematics.Interop.RawColor4(1f, 0.0f, 0.0f, 0.5f));
_graphics.D2D1Context5.FillRoundedRectangle(new RoundedRectangle() { RadiusX = 20, RadiusY = 20, Rect = new SharpDX.Mathematics.Interop.RawRectangleF(10, 10, 630, 470) }, br);
br.Dispose();
_graphics.D2D1Context5.EndDraw();

Then i use this function to get Pixel value from img above:


private static Color4 GetPixel( Bitmap1 created_with_BitmapOption_Target, int x, int y)
        {
            var img1 = new D2D1.Bitmap1(_graphics.D2D1Context5, new SharpDX.Size2(created_with_BitmapOption_Target.PixelSize.Width, created_with_BitmapOption_Target.PixelSize.Height), new BitmapProperties1()
            {
                PixelFormat = new D2D1.PixelFormat(Format.R8G8B8A8_UNorm, D2D1.AlphaMode.Premultiplied),
                DpiX = 96,
                DpiY = 96,
                BitmapOptions = BitmapOptions.CannotDraw | BitmapOptions.CpuRead
            });

            img1.CopyFromBitmap(created_with_BitmapOption_Target);

            var map = img1.Map(MapOptions.Read);
            var size = created_with_BitmapOption_Target.PixelSize.Width * created_with_BitmapOption_Target.PixelSize.Height * 4;
            byte[] bytes = new byte[size];
            Marshal.Copy(map.DataPointer, bytes, 0, size);
            img1.Unmap();
            img1.Dispose();

            var position = (y * created_with_BitmapOption_Target.PixelSize.Width + x) * 4;

            return new Color4(bytes[position], bytes[position + 1], bytes[position + 2], bytes[position + 3]);

        }

Then i get pixel value :


Color4 c4val = GetPixel(img,50, 50);

I get c4value is: Alpha=127; Red=127; Green=0; Blue=0

This color is not the same the color i filled img (Red=1f; G=0.0f; B=0.0f; Alpha = 0.5f;)

Can anybody help where i was wrong in code?

Thank you so much in advance,

HoaHong

 

The Game

Advertisement
1 hour ago, hoahong said:

I get c4value is: Alpha=127; Red=127; Green=0; Blue=0

This color is not the same the color i filled img (Red=1f; G=0.0f; B=0.0f; Alpha = 0.5f;)

Can anybody help where i was wrong in code?

Based on the output and the code, e.g. this:


PixelFormat = new D2D1.PixelFormat(Format.R8G8B8A8_UNorm, D2D1.AlphaMode.Premultiplied)

It looks like you're using premultiplied alpha.

4 minutes ago, Zakwayda said:

Based on the output and the code, e.g. this:



PixelFormat = new D2D1.PixelFormat(Format.R8G8B8A8_UNorm, D2D1.AlphaMode.Premultiplied)

It looks like you're using premultiplied alpha.

I changed to:
 


D2D1.AlphaMode.Ignore

But still the same value.

The Game

I'm not familiar with the API you're using, so I may only be able to be of so much help here. I'll mention though that you said you switched to 'Ignore', but didn't say where, and I see 'Premultiplied' twice in your current code. Also, these values:

(Red=1f; G=0.0f; B=0.0f; Alpha = 0.5f;)

Alpha=127; Red=127; Green=0; Blue=0

Are (assuming I'm not making a mistake) exactly what you'd expect with premultiplied alpha, so if you're still getting the same results, I'd say the chances of the results not being due to premultiplied alpha are low.

Again, I'm not familiar with the API, and I'm not sure what the significance of (apparently) creating a new bitmap for the purpose of getting a pixel value is. In any case, if you're still getting similar results, I'd investigate the premultiplied alpha issue further, as that still seems like the most likely cause to me.

9 hours ago, Zakwayda said:

I'm not familiar with the API you're using, so I may only be able to be of so much help here. I'll mention though that you said you switched to 'Ignore', but didn't say where, and I see 'Premultiplied' twice in your current code. Also, these values:

(Red=1f; G=0.0f; B=0.0f; Alpha = 0.5f;)

Alpha=127; Red=127; Green=0; Blue=0

Are (assuming I'm not making a mistake) exactly what you'd expect with premultiplied alpha, so if you're still getting the same results, I'd say the chances of the results not being due to premultiplied alpha are low.

Again, I'm not familiar with the API, and I'm not sure what the significance of (apparently) creating a new bitmap for the purpose of getting a pixel value is. In any case, if you're still getting similar results, I'd investigate the premultiplied alpha issue further, as that still seems like the most likely cause to me.

Thanks @Zakwayda

After you said in 2nd post, I changed Premultiplied at positionss in code (in creating images) test and got such result, i did not post that code here.

The first bitmap was created with flag 'BitmapOptions.Target' so that i could draw on that bitmap by DeviceContext but i can access pixel value of the bitmap with such flag. That's why i created a second bitmap with flag 'BitmapOptions.CpuRead' to read pixel value.

Do you have any hint for reading pixel of the first bitmap in my code?

Thanks

 

 

 

The Game

14 minutes ago, hoahong said:

Do you have any hint for reading pixel of the first bitmap in my code?

I realize I may be repeating myself, but it seems to me that if you're getting results like this:

(Red=1f; G=0.0f; B=0.0f; Alpha = 0.5f;)

Alpha=127; Red=127; Green=0; Blue=0

Where the output RGB is the input RGB multiplied by the alpha (as in the above example), then it seems almost certain that you're ending up with premultiplied alpha somehow, and the question is simply how. (Just to make sure we're covering all the bases here, I'll point out the obvious - that the input data is normalized while the output data appears to be 8-bit. Presumably you've already accounted for that and recognize that 0.5 and 127 are close to the same value.)

I think my only suggestion at this point would be to post your new, revised code. I don't know if I'll be able to help, but if not, maybe someone familiar with the API will be able to.

7 minutes ago, Zakwayda said:

I think my only suggestion at this point would be to post your new, revised code. I don't know if I'll be able to help, but if not, maybe someone familiar with the API will be able to.

The revised code only change:
 


PixelFormat = new D2D1.PixelFormat(Format.R8G8B8A8_UNorm, D2D1.AlphaMode.Premultiplied)

To:


PixelFormat = new D2D1.PixelFormat(Format.R8G8B8A8_UNorm, D2D1.AlphaMode.Ignore)

 

The Game

It's your call of course, but I'd still recommend posting all the relevant code, like you did before. Among other things, 'Premultiplied' appeared twice in your original code, and even if you've changed it in both locations, it might be helpful for us to be able to see that and to be able to look for other issues as well.

It might also be helpful to clarify if the results you're getting now are exactly the same as before, or are different now but are wrong in some other way. (You could just post a sample input and output pixel value like you did before.)

8 minutes ago, Zakwayda said:

It's your call of course, but I'd still recommend posting all the relevant code, like you did before. Among other things, 'Premultiplied' appeared twice in your original code, and even if you've changed it in both locations, it might be helpful for us to be able to see that and to be able to look for other issues as well.

It might also be helpful to clarify if the results you're getting now are exactly the same as before, or are different now but are wrong in some other way. (You could just post a sample input and output pixel value like you did before.)

The code to create GraphicContext:
 


Factory5 resultFactory;
Adapter4 resultAdapter;
D3D11.Device5 resultDevice;
D2D1.Device5 _d2d1device5;
D2D1.DeviceContext5 _d2d1Devicecontext5;
using (var factory2 = new SharpDX.DXGI.Factory2())
{
	resultFactory = factory2.QueryInterface<Factory5>();

	using (Adapter adapter =  resultFactory.GetAdapter1(0))
		{
			resultAdapter = adapter.QueryInterface<Adapter4>();

			using (var device = new D3D11.Device(resultAdapter, SharpDX.Direct3D11.DeviceCreationFlags.Debug |  			SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport | SharpDX.Direct3D11.DeviceCreationFlags.VideoSupport, SharpDX.Direct3D.FeatureLevel.Level_11_0, SharpDX.Direct3D.FeatureLevel.Level_11_1, SharpDX.Direct3D.FeatureLevel.Level_12_0, SharpDX.Direct3D.FeatureLevel.Level_12_1/*requestedFeatureLevel*/)
                    {
                        DebugName = "Direct3D11 creation"
                    })
                    {
                        resultDevice = device.QueryInterface<D3D11.Device5>();

                        //Create 2D Device & Context
                        var dxgiDevice1 = resultDevice.QueryInterface<SharpDX.DXGI.Device1>();
                        // Dont define f1 as SharpDX.Direct2D1.Factory1, just define f1 as var, this is a trick by system
                        var f1 = new SharpDX.Direct2D1.Factory1();
                        var d2ddv = new SharpDX.Direct2D1.Device(f1, dxgiDevice1);
                        _d2d1device5 = d2ddv.QueryInterface<SharpDX.Direct2D1.Device5>();
                        _d2d1Devicecontext5 = new DX.Direct2D1.DeviceContext5(_d2d1device5, DX.Direct2D1.DeviceContextOptions.EnableMultithreadedOptimizations) { TextAntialiasMode = DX.Direct2D1.TextAntialiasMode.Aliased };

                    }
		}
}

The code to create and draw bitmap in the fist post
 

The Game

7 minutes ago, hoahong said:

The code to create and draw bitmap in the fist post

Ok, I think maybe we're talking past each other here. It's the revised version of the code in the first post that we need to see, because that's where the code related to premultiplied alpha is (or at least some of it). We need to see what changes you've made to that code, and what it looks like now, preferably along with some new sample data showing what sort of results you're getting now.

If that's still not clear, I won't persist further, but if you can post what I described above I'll be happy to take another look.

This topic is closed to new replies.

Advertisement