Fit image to ShaderResourceView and preserve aspect ratio - c#

I'm loading an image into a ShaderResourceView to be used as a background image. This is what I'm currently using:
ShaderResourceView.FromFile(_device, imagepath);
It loads the image into the background, but it stretches both dimensions without regard to the aspect ratio. Is there a way to load an image into the background and preserve aspect ratio?

Ideally ShaderResourceView would provide a setting to automatically respect the image aspect, but below is the next best option.
An existing post on SO fits the image to a specified size, then pads any extra space with whitespace and creates a new image. Link: https://stackoverflow.com/a/2001462/978622
Another post shows how to easily convert from an Image to a bytearray, which is one of the types ShaderResourceView can create a shader from. Link: https://stackoverflow.com/a/3801289/978622
My code which puts it all together:
var original = Image.FromFile(path);
Image resized = FixedSize(original, actualWidth, actualHeight);
var byteImage = ImageToByteArray(resized);
var srv = ShaderResourceView.FromMemory(_device, byteImage);

Related

Resize transparent image with Magick.NET

I got some weird issues when resizing an image with transparency in Magick.NET. I am using Q16-AnyCPU.
I am resizing a 100px image to 400px.
MagickImage image = new MagickImage("test.png");
image.Resize(400, 400);
image.Write("test_resized.png");
I have tried many combinations of image.FilterType and image.Interpolate without any good results.
Only when I use image.AdaptiveResize(400, 400);, it looks somewhat better, but not as expected. The final image I want to resize is much bigger and AdaptiveResize is very slow.
When I disable Alpha via image.Alpha(AlphaOption.Off); I looks quice nice, but I want to keep the alpha.
Source image (the white area is transparent):
What I get:
What I want:
I had to set VirtuaPixelMethod, thanks for the hint:
MagickImage image = new MagickImage("test.png");
image.VirtualPixelMethod = VirtualPixelMethod.Transparent;
image.Resize(400, 400);
image.Write("test_resized.png");

How do I draw a pixel at a specific position on a window?

I need to create a program that will display lines or dots of coordinates read from a txt file. The application will be attached to the output of an eye-tracking program, and will display the data.
How do I display some sort of graphic at a particular coordinate on the screen?
Note: The window is full-screen, and I can use WPF or WinForms.
I would overlay your video with an Image element; something like:
<Grid>
<Image x:Name=TrackingImage />
<MediaElement/>
</Grid>
Then in your code behind; set the source to a WriteableBitmap. The documentation has an excellent sample, but to summarize it here:
WriteableBitmap writeableSource = new WriteableBitmap(100, 100, 96, 96, PixelFormats.Bgra32, null);
// Calculate the number of bytes per pixel.
int _bytesPerPixel = (writeableSource .Format.BitsPerPixel + 7) / 8;
// Stride is bytes per pixel times the number of pixels.
// Stride is the byte width of a single rectangle row.
int _stride = writeableSource .PixelWidth * _bytesPerPixel;
private void SomeUpdateFunction()
{
// Define the rectangle of the writeable image we will modify.
// The size is that of the writeable bitmap.
Int32Rect _rect = new Int32Rect(0, 0, _wb.PixelWidth, _wb.PixelHeight);
//Update writeable bitmap with the colorArray to the image.
_wb.WritePixels(_rect, pixelBuffer, _stride, 0);
TrackingImage.Source = writeableSource;
}
Note that it uses WritePixels (specifically; this overload: MSDN)
Obviously you will need to modify the parameters to get the correct pixel in the correct place. This is the right technique though.
This answer was inspired by: Drawing Pixels in WPF It might be worth looking at if you need more info.
Various bitmap formats are instructions to put colored dots at specific locations. Why not use something like that? What ELSE do you need it to do?
Regarding your eye-tracking and point-data comment, if you want to composite it with captured video, then you don't need to worry about how to display the images so much as you need to think about how to add the dots to the video itself. The video player will do the displaying.
From what I know about screen-capture and video codecs (not a whole lot) it will be best to work with the uncompressed video before it gets encoded. Otherwise you'll have to decode, add, and re-encode. I'd look for a way to hook into the capture program and add the live eye-tracker data to the captured frames.

Images Scaling Down in draw in C#

Alright guys last little bit of this project I'll ask for help on I promise.
So I go to load the images, works fine however I notice upon loading that the dimensions of the image have been scaled down in the y to 300 (all are a constant value of 433) and up or down from their original width to 600.
I'm using the following method to load them
foreach (string file in Directory.EnumerateFiles(imagePath, "*.JPG"))
{
Image contents = Image.FromFile(file);
treesImage[count] = contents;
count++;
}
and this is the resulting image when I have it loaded.
http://i.stack.imgur.com/Q40kK.png
As you can see the image below the red rectangle is quite small
Any help would be appreciated. If you require any more information please post below and I'll make sure to edit the original question with the relevant information as soon as humanly possible.
EDIT: I am using a simple windows form application and not another graphical framework for my own reasons.
Thanks in advance :)
I'll assume you are using a PictureBox control to display the image.
When someone chooses a tree from your map, you obviously set the PictureBox Image property to the image object referenced by the index in the array. Use the Image object to set the ClientSize of the PictureBox control.
...
Image img = treesImage[idx];
MyPictureBox.SizeMode = PictureBoxSizeMode.Normal;
MyPictureBox.ClientSize = new Size(img.Width,img.Height);
MyPictureBox.Image = img;
...
Alternately you can define one size for your PictureBox and force all the images to be scaled to that size by setting the control SizeMode property to StretchImage declaratively.
I would recommend that you create a simple class (MyImageInfo for example) that would store the Path, Width, and Height of the images found in your first function into a list and then just as before when a user clicks to view an image you set the width and height of the PictureBox and then call the LoadAsync(path) method to get the image. then you aren't storing all images in memory at once, just as you need them since it doesn't look like this requires a lot of quick jumping from image to image.

How to zoom an image in&out in C#?

I want to implement zoom for an image. I don't want to resize the PictureBox, but the image itself.
How do I do this?
One solution is:
Create new image of the desired size (for example 200% or 50% of original image size)
Draw original image to new image using Graphics.DrawImage(Image, Rectangle);, which draws the given image to the new image at the given position with the given size
Set new image as source for the PictureBox
Another way is to simple create a new bitmap instance like that:
Size newSize = new Size((int)(originalBitmap.Width * zoomFactor), (int)(originalBitmap.Height * zoomFactor));
Bitmap bmp = new Bitmap(originalBitmap, newSize);
I used a web browser to achieve this.
//loads the image
myWebBrowser.Navigate(#"C:\myimage.png");
From there I used SendKeys to zoom in and out
myWebBrowser.Select(); //Selects browser.
SendKeys.Send("^{+}"); //Sends the control + key combo, causing the browser to zoom in. Replace the "+" with a "-" to zoom out.
It's a bit of a weird method, but it worked really well for me. I hope you find this helpful!

C#: Retain size despite different resolution using Graphics.DrawImage

I am trying to draw two images side-by-side using the C# Drawing namespace.
Here is a very simple example that assumes we have two images of the same height:
Image[] oldImages = GetOldImages();
var newImage = new Bitmap(oldImages[0].Width + oldImages[1].Width, 800);
using (var newImageGraphics = Graphics.FromImage(newImage))
{
newImageGraphics.DrawImage(oldImages[0], 0, 0);
newImageGraphics.DrawImage(oldImages[1], oldImage[0].Width, 0);
newImageGraphics.Save();
}
This works OK if the resolution of the two old images are the same.
However, if the resolutions are different then the image is resized, causing problems. For example, if the first image has a different resolution, then the second image will be positioned incorrectly.
Does anyone know how I can fix this problem easily? Ideally I want the original image's height and width to remain the same when they are drawn on to the new image.
Try this trick:
Bitmap picture_1 = new Bitmap(picture_1_path);
Graphics graphics = Graphics.FromImage(picture_1);
Bitmap picture_2 = new Bitmap(picture_2_path);
picture_2.SetResolution(graphics.DpiX, graphics.DpiY);
//Then do with pictures anything
Basically you'll need to resize the second image before adding to the new image.
Though as you say you want to retain the original height and width you'll need to change the canvas size of the second image. This increases the size of the image by adding empty space around the actual image. If the second image is larger than the first you'll need to do this to the first image instead.

Categories

Resources