Gtk#: How to convert a Gtk.Image in a Gdk one? - c#

I would like to write a simple 2D game in Mono/Gtk#with MonoDevelop 2.4. My first interest was to display a PNG image for the player character in the Window canvas (later I will respond to keyboard events in order to move it). However, I have found out a disturbing problem here: while I get a Gtk.Image object for the player character, the DrawImage method of the Gdk Window needs a Gdk image. How could I convert the first one to the latter?
public static void ShowImage(Gdk.Window w, Gtk.Image image)
{
w.DrawImage( Style.ForegroundGC( StateType.Normal ),
image, // ERROR
0, 0, image.Pixbuf.Width, image.Pixbuf.Height,
image.Pixbuf.Width, image.Pixbuf.Height
);
}
This is might appear simplistic, but honestly I haven't found the answer yet.

Gtk.Image.ImageProp is a property holding the Gdk.Image held in the Gtk.Image widget.
public static void ShowImage(Gdk.Window w, Gtk.Image image)
{
w.DrawImage( Style.ForegroundGC( StateType.Normal ),
image.ImageProp, // TRY THIS
0, 0, image.Pixbuf.Width, image.Pixbuf.Height,
image.Pixbuf.Width, image.Pixbuf.Height
);
}
Here is a link to the GTK# documentation.

Gtk.Image is a widget (or a control in winforms terminology).
see: http://library.gnome.org/devel/gtk/unstable/GtkImage.html
From your problem description I don't think you want to be using a Gtk.Image, but a Gdk.Image.
IE. change your ShowImage method to: public static void ShowImage(Gdk.Window w, Gdk.Image image)

Related

C# System.Drawing.Image.get_Width() throws exception on WinForms form is maximized

I writing Windows Forms Application application which should show image on the PictureBox control.
To retrieve this image from DICOMDIR file I use fo-dicom library (driven by this guide):
....
private void MainForm_Load(object sender, EventArgs e)
{
ImageManager.SetImplementation(WinFormsImageManager.Instance);
}
....
// this function is just for example
// real function is bit complicated
private void ShowImage()
{
// Getting DICOM file, retrieving all info from it
// Getting dicomDataset instance
....
var id = dicomDataset.Get<string>(DicomTag.ReferencedFileID, -1);
var dicomImage = new DicomImage(id);
var bitmap = dicomImage.RenderImage().AsBitmap();
pictureBox.Image = bitmap ?? pictureBox.ErrorImage;
}
When image is retrieving all works fine. But as soon as I maximize my MainForm, I got System.ArgumentException with Parameter is not valid message:
It looks like this is a .NET Framework bug, but maybe there is a way to fix it by overrideing OnPaint() method of PictureBox control?
Have anyone see this bug previously?
Thanks in advance.
P.S. During development this project I use following software:
Windows 10 x64
Visual Studio 2017 Community Edition
.NET Framework 4.5.1
fo-dicom version 3.0.2
EDIT #1
The same issue with Panel instead of PictureBox:
You are facing a known and already fixed bug in fo-dicom 3.0.2. See also https://github.com/fo-dicom/fo-dicom/issues/634.
For performance reason the Bitmap, that DicomImage.RenderImage().AsBitmap() returns, does not have its own pixel data, but has a pointer to the bytes of DicomImage. So the AsBitmap() does not duplicate all the pixel data in memory.
But if you instanciate the DicomImage in a local variable and save the Bitmap in the control, then the DicomImage is disposed at the end of the method and the pixel data gets garbace collected. The next time, the Bitmap tries to access the pixel data this exception happens.
The next release will have two methods: AsSharedBitmap() - the same as now but more obvious to the user - and AsClonedBitmap().
The workaround now is, to copy the pixel data manually by calling:
var bitmap = dicomImage.RenderImage().AsBitmap().Clone();

Show A D3DImage With SharpDX

I intend to develop an application to get an image from a file and show it with Directx9 . I have used this code but I got the Error on SetBackBuffer Method!!
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
private void d3dImage_IsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (d3dImage.IsFrontBufferAvailable)
{
// (Re)initialization:
Bitmap b = new Bitmap(#"C:\Users\newuser\Desktop\3.jpg");
IntPtr Mysurface = b.GetHbitmap();
if (Mysurface != IntPtr.Zero)
{
d3dImage.Lock();
//Error occurred this line
d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, Mysurface);
d3dImage.Unlock();
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
}
else
{
// Cleanup:
CompositionTarget.Rendering -= CompositionTarget_Rendering;
//Sample.Cleanup();
}
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
// Now that we can get an HWND for the Window, force the initialization
// that is otherwise done when the front buffer becomes available:
d3dImage_IsFrontBufferAvailableChanged(this,
new DependencyPropertyChangedEventArgs());
}
private void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (d3dImage.IsFrontBufferAvailable)
{
d3dImage.Lock();
//Sample.Render();
// Invalidate the whole area:
d3dImage.AddDirtyRect(new Int32Rect(0, 0,
d3dImage.PixelWidth, d3dImage.PixelHeight));
d3dImage.Unlock();
}
}
actually I want show an image in d3dimage in a WPF project. Can any one help me? I could not find good resources about Directx and C#!!!
Edited Using Sharpdx and Got new Error "'HRESULT: [0x8876086C], Module: [SharpDX.Direct3D9], ApiCode: [D3DERR_INVALIDCALL/InvalidCall], "
s = new SharpDX.Direct3D9.Surface(IntPtr.Zero);
SharpDX.Direct3D9.Surface.FromFile(s, #"C:\Users\newuser\Desktop\3.jpg", SharpDX.Direct3D9.Filter.None, 1);
You're setting the back buffer to a Bitmap. You cannot do this. The back buffer must be of type IDirect3DSurface9. This is noted in the documentation for the SetBackBuffer method.
In order to use DirectX9 (unmanaged) from C# (managed), you need to use a wrapper library. Are you using one? If not, there are several available. SlimDX and SharpDX seem to be the most popular. Using any of the wrapper libraries, you can create a IDirect3DSurface9that you render to with a IDirect3DDevice9, and attach that surface to your WPF control. Your rendered content will then appear in the control.
I think using DirectX may be overkill for what you need, but I'm not sure what the entire scope of your project is.
Solution using SharpDX
I put together a working example that uses SharpDX to display an image within a D3DImage. This is very basic and doesn't include proper error handling. It's just meant to get you going in the right direction.
Step 1 - Create D3D9 device
To create the necessary surfaces, you will need a Direct3D 9 Device. The following code will create a Device using SharpDX.
//Create the d3d interface.
Direct3D d3d = new Direct3D();
//Get a handle to the WPF window. This is required to create a device.
IntPtr windowHandle = new WindowInteropHelper(this).Handle;
//Create a device. Using standard creation param.
//Width and height have been set to 1 because we wont be using the backbuffer.
//Adapter 0 = default adapter.
PresentParameters presentationParams = new PresentParameters(1,1);
Device d3dDevice = new Device(d3d, 0, DeviceType.Hardware, windowHandle, CreateFlags.HardwareVertexProcessing, presentationParams);
Step 2 - Create the image surface
Create a surface to hold the image data.
//Create an empty offscreen surface. Use SystemMemory to allow for surface copying.
Surface imageSurface = Surface.CreateOffscreenPlain(d3dDevice, ImageWidthPixels, ImageHeightPixels, Format.A8R8G8B8, Pool.SystemMemory);
//Fill the surface with the image data.
Surface.FromFile(imageSurface, "dx.jpg", Filter.None, 0);
Step 3 - Create the render target surface
Create the surface that acts as a render target. This is the type of surface required by D3DImage.
//Create the surface that will act as the render target.
//Set as lockable (required for D3DImage)
Surface target = Surface.CreateRenderTarget(d3dDevice, ImageWidthPixels, ImageHeightPixels, Format.A8R8G8B8, MultisampleType.None, 0, true);
Step 4 - Copy the image surface to the render target.
The image surface can be copied into the render target surface using the Device.UpdateSurfaces method. Note that in the previous steps, both surfaces were created with the same format (A8R8G8B). Watch out for this. It's necessary for surface copies.
//Copy the image surface contents into the target surface.
d3dDevice.UpdateSurface(imageSurface, target);
Step 5 - Attach the surface to D3DImage
You now have a surface that contains your image and that can be used with 'D3DImage`. Make sure you use the target surface, not the image source surface.
this.wpfImageSource.Lock();
this.wpfImageSource.SetBackBuffer(D3DResourceType.IDirect3DSurface9, target.NativePointer);
this.wpfImageSource.AddDirtyRect(new Int32Rect(0, 0, wpfImageSource.PixelWidth, wpfImageSource.PixelHeight));
this.wpfImageSource.Unlock();
Results
The image appears!

C# Managed DirectX sprite2D locating bug?

I want to draw 2D sprite.
And here is strange thing: if i Sprite.Draw2D with first overload:
using (Sprite Spr = new Sprite(Gfx))
{
Spr.Begin(SpriteFlags.AlphaBlend);
int SprY = Gfx.PresentationParameters.BackBufferHeight/2;
int SprX = Gfx.PresentationParameters.BackBufferWidth/2;
Spr.Draw2D(Tex, new Point(0,0), 0.0f, new Point(SprX,SprY), Color.White);
Spr.End();
while (!Spr.Disposed)
Spr.Dispose();
}
It locating right in 128,128.
But I want to scale-down my image.
So i use 3rd overload of Sprite.Draw2D:
Spr.Draw2D(Tex, new Rectangle(0, 0, 1024, 1024), new Rectangle(0,0,256,256), new Point(SprX,SprY) , Color.White);
Then, it draws to weired position(but correct-sized).
I found-out that width of screen in case of 3rd overload = 1280.
And no matter of PresentationParameters or ViewPort sizes. Even on other machine it is 1280, and center will be 640.
I've tryed to debug Gfx(Device) object and see if any appereance of '1280' number, and it is appear in Gfx.DisplayMode. Unfortunatly, i cant set this parameter because "Device.SetDisplayMode is deprecated" as MSDN says. And DisplayMode.Width is differs between two computers i've test my 'game' on.
Probably i've missed something realy HUGE and stack on it.
By the way, im using DirectX libs from "C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0" if this matters.

XNA 3.1 DrawUserPrimitives with Anti Aliasing - MultiSampling doesn't work?

So this is a continuation of a question I asked earlier today. I've built myself some nice looking ribbon trails using XNA 3.1's DrawUserPrimitives method, essentially by expanding a polygon as motion occurs. It all looks super sleek and nice, except for one thing - anti-aliasing. I cannot for the life of me work out how to apply it.
I've set this in the game constructor:
graphics.PreferMultiSampling = true;
And I've also added this to test for the hardware:
graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>((sender, e) =>
{
PresentationParameters parameters = e.GraphicsDeviceInformation.PresentationParameters;
parameters.MultiSampleQuality = 0;
#if XBOX
pp.MultiSampleType = MultiSampleType.FourSamples;
return;
#else
int quality;
GraphicsAdapter adapter = e.GraphicsDeviceInformation.Adapter;
SurfaceFormat format = adapter.CurrentDisplayMode.Format;
if (adapter.CheckDeviceMultiSampleType(DeviceType.Hardware, format, false, MultiSampleType.FourSamples, out quality))
{
parameters.MultiSampleType = MultiSampleType.FourSamples;
}
else if (adapter.CheckDeviceMultiSampleType(DeviceType.Hardware, format, false, MultiSampleType.TwoSamples, out quality))
{
parameters.MultiSampleType = MultiSampleType.TwoSamples;
}
#endif
});
By adding some print lines, I know my hardware can support 4 sample AA, but this all seems to make no difference. I just can't seem to get this to work.
Here's a screenshot of one of my trails with all of that code applied:
I'd really appreciate some help. I looked at this a while ago for a solution to a different problem, and couldn't get it to work then, either.
Well, cheers.
Fixed this one, too!
The issue was that, while the back buffer was getting the right anti-alias settings, the render target wasn't. This meant that drawing to the render target was done without AA, but the texture that was then drawn to the back buffer was done with it. I've fixed it now.

CA overlay on UISegmentedControl is overwritten in iOS5

I have the following code, which in iOS 4 produces the look of a "disabled" UISegmentedControl. As the attentive reader will notice, I am developing in MonoTouch, thus the c# syntax.
private void MakeOverlayOnLastRatingSegment()
{
RemoveOverlayOnLastRatingSegment();
lastRatingDisabledLayer = new CALayer();
lastRatingDisabledLayer.Frame = new RectangleF(new PointF(0, 0), segmLastRating.Frame.Size);
lastRatingDisabledLayer.CornerRadius = 10.0f;
lastRatingDisabledLayer.BackgroundColor = UIColor.FromRGBA(0.5f, 0.5f, 0.5f, 0.2f).CGColor;
segmLastRating.Layer.AddSublayer(lastRatingDisabledLayer);
}
And the result is:
But on iOS5 the result is a bit different. The segment before the selected cell is written on top of my gray layer. It takes a bit close look - more evident on a real device instead of simulator. For some reason the screendump from the simulator is very light.
Has anyone else experienced this, and do somebody have a workaround?
Best regards
/Anders
Could you add your overlay layer to the layer of the segmented control’s superview? Or perhaps the segmented control’s layer’s superlayer?

Categories

Resources