SharpDx Save Bitmap to File - c#

I have a Sharpdx Direct2D1 Bitmap from the render target. I want to save it to a file as an image though. This is for test purposes. I am not sure if i need a WIC bitmap for that or how to convert these bitmaps. Or how to receive the WIC bitmap in the first place.
Also i can't find an easy explanation how to save this bitmap to a file in general.
Any help appriciated.
Edit:
I'm using this approach now: http://www.rolandk.de/wp/2013/06/inhalt-der-rendertarget-textur-in-ein-bitmap-kopieren/
It is in German, but what he says is, that you have to copy the resource of the
render target to a staging resource to have access via the cpu. Then copy the contents over to a bitmap.
I'm trying this approach then finally using bitmap.Save(filename). But somehow the bitmap stays empty. Maybe i miss to encode the file correctly. But seems more like I don't get the data from the back buffer target at all.

If you have your image in a WicBitmap it is very easy to move it into a GDI+ bitmap and save it from there:
var pixelData = new byte[width*height*4];
wicBitmap.CopyPixels(pixelData, width*4);
var bmp = new System.Drawing.Bitmap(width, height);
var bd = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height), ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
Marshal.Copy(pixelData, 0, bd.Scan0, pixelData.Length);
bmp.UnlockBits(bd);
There may or may not be better ways to solve this. But this is the one I have used successfully.

The question is answered by Dan Bysröm, if you have the wicBitmap and then simply copy the data to the gdi bitmap.
I solved my particular problem with the link I posted in the edit part though. I did not use wic or anything, because that maybe was a totally wrong approach for my problem in the first place.
The question that arised in the edit part was solved by not using CopyResource(...) but CopySubResource(...) instead with default parameter to copy all. I am not sure why CopyResource(...) did not work though.

Related

How to copy a monochrome bitmap in resources to disk as monochrome bmp in c#

Using WinForm, I have a small bmp file in the resources which is just black and white so two colour, saved as Lion.bmp. I need it just two colour as bmp. When the user clicks on a button a dialog comes up asking them where they want to save this. I want to then copy the resource to that space but save it as two colour bmp just as the original in resources. I have managed to save it as all manner of other files and even a 32 bit bitmap but not a two colour bitmap.
First I thought I would just copy byte for byte but found that was not possible with my knowledge. I could probably do it if I knew how.
Next I thought I would just create a new bitmap and save it
new Bitmap(Resources.Lion).Save(dialog.SelectedPath + "\\lion.bmp");
This compiled and I was happy till I realised I was saving a PNG file called .bmp. Next I find that I can add an Image format so I try
new Bitmap(Resources.Lion).Save(dialog.SelectedPath + "\\lion.bmp", ImageFormat.Bmp);
Again it compiles and saves a file but even though the resource is monochrome it saves it now a 32bit colour depth and not 2. I next try to just write it out as a stream of bytes which was my original plan
File.WriteAllBytes((dialog.SelectedPath + "\\lion.bmp"), Resources.Lion);
That does not compile as it says Resources.Lion is not a byte[] but I think it must be as it is in resources. Next I find in Bitmap I can have
Encoder.ColourDepth, 2
I think this would work but I cannot work out how to use that as ever time I try it will not compile.
new Bitmap(Resources.Lion).Save(dialog.SelectedPath + "\\lion.bmp", ImageFormat.Bmp, (Encoder.ColorDepth,2));
I guess I need to ask those wiser than me what the syntax may be to get this to work so that I can copy the monochrome bitmap from resources to monochrome bitmap on disk.
In the end a colleague came up with the suggestion of cloning the resource "Lion" that I wanted.This has worked. The code I used is below:
Resources.Lion.Clone(new Rectangle(0, 0, Resources.Lion.Width, Resources.Lion.Height),System.Drawing.Imaging.PixelFormat.Format1bppIndexed).Save(dialog.SelectedPath + "\\lion.bmp", ImageFormat.Bmp);

save greyscale image as color JPEG

I'm handling a lot of different image formats within my application. Luckily I was able to source out the biggest part of dealing with image formats to C#WPF. However, I've got an issue when saving images:
I'd like to save my images as JPEGs using JpegBitmapEncoder with an RGB profile. This works all fine for color image formats. However, when handling images i.e. of format Gray16 or Gray8, the resulting JPEGs will have a Grayscale profile. I really do need an RGB profile for my JPEGs!
I know that I could just create a new WriteableBitmap in Bgra32, copy to it the data and use it to create the JPEG. This however means, that I would need to handle the different image formats myself. Most importantly I believe that this detour would be quite inefficient computationally (I need to convert a lot of image data!).
Also I can't use any solutions outside of C#/WPF (like Imagemagick).
I hope that there's a way to solve this easily and efficiently. I found no way to configure JpegBitmapEncoder for this and I had a try with ColorConvertedBitmap but to no avail!
Any ideas?
The hint for FormatConvertedBitmap gave me the solution to my problem! Thanks RononDex!
FormatConvertedBitmap convertImg = new FormatConvertedBitmap(img, PixelFormats.Bgra32, null, 0);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(convertImg));
encoder.Save(stream);

Load a bitmap from file in RGB format (without alpha)

i simply want to load a .BMP file and get the Bitmap object in 24bit RGB format (or 32bit in RGB format).
All methods I tried return a Bitmap/Image object with PixelFormat = Format32bppArgb. Even if of course BMPs don't have alpha.
new Bitmap(System.Drawing.Image.FromFile(fileName, true));
new Bitmap(fileName);
I currently solve the problem by copying the first object to another in memory bitmap at 24bit RBG.
Is there a single method to do it?
Thanks
As far as I can tell it is not possible to specify the PixelFormat for loading bitmaps using the classes in System.Drawing. To convert the bitmap check this question: Converting Bitmap PixelFormats in C#
This is currently the top answer there:
Bitmap orig = new Bitmap(#"c:\temp\24bpp.bmp");
Bitmap clone = new Bitmap(orig.Width, orig.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
using (Graphics gr = Graphics.FromImage(clone)) {
gr.DrawImage(orig, new Rectangle(0, 0, clone.Width, clone.Height));
}
// Dispose orig as necessary..
One option would be to put that in a function which takes a filename and PixelFormat. That hides the ugly code, which has its ups and downs since it also hides the fact it is probably not that efficient.
According to the linked SO question using the Clone method not always works.
You can clone it to a RGB format one:
var bitmapInRgbFormat = loadedBitmap.Clone(new Rectangle(0, 0, loadedBitmap.Width, loadedBitmap.Height), PixelFormat.Format32bppRgb)
Exactly what do you mean by copying the first object to another?
To achieve what you want to do, meaning loading an image and converting it to 24 bit, just get the graphics context of a second bitmap that matches the size and that is RGB, and paint the original bitmap onto this one.

Image manipulation in C#

I am loading a JPG image from hard disk into a byte[]. Is there a way to resize the image (reduce resolution) without the need to put it in a Bitmap object?
thanks
There are always ways but whether they are better... a JPG is a compressed image format which means that to do any image manipulation on it you need something to interpret that data. The bimap object will do this for you but if you want to go another route you'll need to look into understanding the jpeg spec, creating some kind of parser, etc. It might be that there are shortcuts that can be used without needing to do full intepretation of the original jpg but I think it would be a bad idea.
Oh, and not to forget there are different file formats for JPG apparently (JFIF and EXIF) that you will ened to understand...
I'd think very hard before avoiding objects that are specifically designed for the sort of thing you are trying to do.
A .jpeg file is just a bag o' bytes without a JPEG decoder. There's one built into the Bitmap class, it does a fine job decoding .jpeg files. The result is a Bitmap object, you can't get around that.
And it supports resizing through the Graphics class as well as the Bitmap(Image, Size) constructor. But yes, making a .jpeg image smaller often produces a file that's larger. That's an unavoidable side-effect of Graphics.Interpolation mode. It tries to improve the appearance of the reduced image by running the pixels through a filter. The Bicubic filter does an excellent job of it.
Looks great to the human eye, doesn't look so great to the JPEG encoder. The filter produces interpolated pixel colors, designed to avoid making image details disappear completely when the size is reduced. These blended pixel values however make it harder on the encoder to compress the image, thus producing a larger file.
You can tinker with Graphics.InterpolationMode and select a lower quality filter. Produces a poorer image, but easier to compress. I doubt you'll appreciate the result though.
Here's what I'm doing.
And no, I don't think you can resize an image without first processing it in-memory (i.e. in a Bitmap of some kind).
Decent quality resizing involves using an interpolation/extrapolation algorithm; it can't just be "pick out every n pixels", unless you can settle with nearest neighbor.
Here's some explanation: http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
protected virtual byte[] Resize(byte[] data, int width, int height) {
var inStream = new MemoryStream(data);
var outStream = new MemoryStream();
var bmp = System.Drawing.Bitmap.FromStream(inStream);
var th = bmp.GetThumbnailImage(width, height, null, IntPtr.Zero);
th.Save(outStream, System.Drawing.Imaging.ImageFormat.Jpeg);
return outStream.ToArray(); }

8bpp Bitmap format on the Compact Framework

I am messing around with Conway's Game of Life - http://en.wikipedia.org/wiki/Conway's_Game_of_Life
I started out coding algorithmns for winforms and now want to port my work onto windows mobile 6.1 (compact framework). I came across an article by Jon Skeet where he compared several different algorithmns for calculating next generations in the game. He used an array of bytes to store a cells state (alive or dead) and then he would copy this array to an 8bpp bitmap. For each new generation, he works out the state of each byte, then copies the array to a bitmap, then draws that bitmap to a picturebox.
void CreateInitialImage()
{
bitmap = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed);
ColorPalette palette = bitmap.Palette;
palette.Entries[0] = Color.Black;
palette.Entries[1] = Color.White;
bitmap.Palette = palette;
}
public Image Render()
{
Rectangle rect = new Rectangle(0, 0, Width, Height);
BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);
Marshal.Copy(Data, 0, bmpData.Scan0, Data.Length);
bitmap.UnlockBits(bmpData);
return bitmap;
}
His code above is beautifully simple and very fast to render. Jon is using Windows Forms but now I want to port my own version of this onto Windows Mobile 6.1 (Compact Framework) but . . . .there is no way to format a bitmap to 8bpp in the cf.
Can anyone suggest a way of rendering an array of bytes to a drawable image in the CF. This array is created in code on the fly (it is NOT loaded from an image file on disk). I basically need to store an array of cells represented by bytes, they are either alive or dead and I then need to draw that array as an image. The game is particularly slow on the CF so I need to implement clever optimised algoritmns but also need to render as fast as possible and the above solution would be pretty dam perfect if only it was available on the compact framework.
Many thanks for any help
Any suggestions?
You could have a look at GDI+ for CF. It's basically a wrapper for most of the GDI implemented in WinCE. Here's a link to the source code and a writeup: http://community.opennetcf.com/articles/cf/archive/2007/10/31/using-gdi-on-windows-mobile.aspx
I think ImagingFactoryClass.CreateBitmapFromBuffer() looks like a good place to start.
Ok, how about this:
use the Bitmap.Save() method to save to a MemoryStream instead of a file;
when you save to the MemoryStream, you get to name the ImageFormat as "GIF" (this is equivalent to 8bpp in .Net, according to this: http://support.microsoft.com/kb/318343)
use MemoryStream.Write() to change whatever data you want in the image, or copy the data using MemoryStream.ToArray() if that jives better.
After you change the MemoryStream, you'll probably have to copy it back into the Bitmap, or make a new Bitmap. If you do make a new Bitmap, be sure to Dispose() the old one, to avoid memory leaks.
Hi Rocjoe and thanks again for the help, I have tried the following
Image bmp = new Bitmap(10, 10);
byte[] array = ImageToByteArray(bmp);
public byte[] ImageToByteArray(Image img)
{
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Gif );
return ms.ToArray();
}
The array coming back has over 870 bytes in it, It seems to hold all sorts of header info, padding and what have you. so again it does not work...

Categories