Converting Bitmap to GDK# PixBuff - c#

How can I convert a System.Drawing.Bitmap to GDK# Image so that I can set to the image widget.
I have tried this...
System.Drawing.Bitmap b = new Bitmap (1, 1);
Gdk.Image bmp = new Gdk.Image (b);
UPDATE:
Bitmap bmp=new Bitmap(50,50);
Graphics g=Graphics.FromImage(bmp);
System.Drawing.Font ff= new System.Drawing.Font (System.Drawing.FontFamily.GenericMonospace, 12.0F, FontStyle.Italic, GraphicsUnit.Pixel);
g.DrawString("hello world",ff,Brushes.Red,new PointF(0,0));
MemoryStream ms = new MemoryStream ();
bmp.Save (ms, ImageFormat.Png);
Gdk.Pixbuf pb= new Gdk.Pixbuf (ms);
image1.Pixbuf=pb;
Exception:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> GLib.GException: Unrecognized image file format
at Gdk.PixbufLoader.Close()
at Gdk.PixbufLoader.InitFromStream(Stream stream)
at Gdk.PixbufLoader..ctor(Stream stream)
at Gdk.Pixbuf..ctor(Stream stream)

One ugly, but working, way is to store the bitmap as a PNG in a MemoryStream.
To save the Bitmap, you can use the Save method:
b.Save(myMemoryStream, ImageFormat.Png);
That was easy enough. Loading the PNG data into the Gdk# Pixbuf is also rather easy; you can use the appropriate constructor:
Pixbuf pb = new Gdk.Pixbuf(myMemoryStream);
You may need to reset the memory stream so the reading position is at the start of the stream before creating the Pixbuf.
A word of caution: I do not consider this the best, or even a "good" solution. Transferring data between two object-oriented data structures by serializing and deserializing the data has a certain code smell to it. I genuinely hope someone else can come up with a better solution.
EDIT: As for the used libraries: This answer uses only plain GDI+ (System.Drawing.Bitmap) and Gdk# (Gdk.Pixbuf). Note that a Gtk.Image is a widget that displays a Gdk.Pixbuf. As such, Gtk.Image is the equivalent of Windows Forms' PictureBox, whereas Gdk.Pixbuf is roughly equivalent to Windows Forms' System.Drawing.Bitmap.
EDIT2: After testing your code, I have found that there are three additional preconditions to ensure before you can run your minimum example:
As suspected above, you must reset the stream position to the beginning of the after saving your Bitmap and before loading your Pixbuf: ms.Position = 0;
You must compile the application for x86 CPUs.
You must invoke Gtk.Application.Init(); before you do anything with Pixbuf.

You may draw in Gtk# like in Winforms. For this you must obtain System.Drawing.Graphics object and then you may draw lines, images and text on it. You may do it like this: 1. Create new Widget. 2. Subscribe on ExposeEvent. 3. On event handler write some code:
protected void OnExposeEvent(object o, ExposeEventArgs e)
{
Gdk.Window window = e.Event.Window;
using (System.Drawing.Graphics graphics =
Gtk.DotNet.Graphics.FromDrawable(window))
{
// draw your stuff here...
graphics.DrawLine(new System.Drawing.Pen(System.Drawing.Brushes.Black), 0, 0, 30, 40);
}
}
Also you need to add reference on gtk-dotnet.dll.

try this ....
Gdk.Pixbuf pixbufImage = mew Gdk.Pixbuf(#"images/test.png");
Gtk.Image gtkImage = new Gtk.Image(pixbufImage);
Gdk.Image gdkImage = gtkImage.ImageProp;

Related

Convert bitmap from 16bpp to 8bpp in C#

I have a Bitmap with 16bpp. I want to convert that image in my ASP.NET side in a 8bpp image.
I tried a lot of options which I found in the internet but nothing works for me.
I also tried that way: C# Converting 32bpp image to 8bpp
But if I want to save the file, I get the following error:
Exception Details: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+.
Line 278: System.Drawing.Image img2 = Convert(bm_resize);//byteArrayToImage(gray);
Line 279:
Line 280: img2.Save(helper+"grey2.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
Line 281: }
Line 282:
Is there any correct way for my problem?
Full Code:
System.Drawing.Image img2 = Convert(bm_resize);
img2.Save(path+"test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
public static System.Drawing.Image Convert(Bitmap oldbmp)
{
using (MemoryStream ms = new MemoryStream())
{
oldbmp.Save(ms, ImageFormat.Gif);
ms.Position = 0;
return System.Drawing.Image.FromStream(ms);
}
}
The problem is caused by disposing the memory stream before the image is saved.
I believe GDI+ requires the memory stream to persist while you are still working with an Image created from the memory stream.
See the Microsoft Support article.
I use a little helper function to create 1 bpp monochrome bitmaps in .NET. Check out this link, it also works great for 8 bpp
http://www.wischik.com/lu/programmer/1bpp.html
hope this could help!
AForge.Net has a good collection of free (under Lesser GPL License) routines for such changes and a lot more. Conversion of 16bpp to 8bpp is as simple as this.

Create a graphic image dynamically using C#

This is a .net web site. I have a list of 100 x,y coordinates.
I need to display 100 octagonal shapes the centre point of which sits at the respective co-ordinate.
I toyed with doing this by passing an array to javascript and dynamically creating and positioning the images. But it looks awful and resizing the browser window causes problems etc.
So, can I create a graphic myself? I saw this code answering a similar question:
using (Bitmap bmp = new Bitmap(10, 10))
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.White);
g.DrawLine(Pens.Black, new PointF(9.56f, 4.1f),
new PointF(3.456789f, 2.12345f));
}
bmp.Save(#"c:\myimage.jpg", ImageFormat.Jpeg);
}
Can you draw octagons easily enough using this?
However, when I try to run the code above, I am getting this error.
A generic error occurred in GDI+
I don't want to spend a long time working out out to draw octagons etc. if I can't get it to run.
One last thing, I don't need to save the graphic, I just want to display it as though it were an image I'm getting from the images folder.
Edit: Further to suggestion below I have modified the code like this:
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] buffer = ms.GetBuffer();
HttpContext.Current.Response.OutputStream.Write(buffer, 0, buffer.Length);
}
This is putting my drawing on the screen. Is there anything that should be tweaked?
You probably don't have write access to C:\.
Instead of saving to disk, you should save to a MemoryStream, then render it to the HTTP response. (inside of an ASHX or MVC action)

Opening an image file to a Bitmap class as 32bppPArgb

Does .NET support PixelFormat conversions? I can't find any methods or constructors to do what I want.
I am allowing the user to choose any image file and I am creating a new Bitmap class from the file.
Then I am drawing the image using custom painting. It's very slow and I am told that the GDI is much faster dealing with images in the 32bppPArgb pixel format.
How do I perform the conversion? Assuming I have a string for the filename which could be a JPEG, TIF, PNG, etc., and I want to load it to a Bitmap class.
Edit:
Here is what I am trying to do, but it's not loading the image properly. The image is not filling the entire bitmap when I draw it.
using (Bitmap tempImage = new Bitmap(filename))
{
Image = new Bitmap(tempImage.Width, tempImage.Height, PixelFormat.Format32bppPArgb);
using (Graphics g = Graphics.FromImage(Image))
{
g.DrawImageUnscaled(tempImage, 0, 0);
}
}
If you have a scaling issue it is not caused by the pixel format. Instead, it is likely caused by DPI settings in the source image file. Try this instead of .DrawImageUnscaled:
g.DrawImage(
tempImage,
new Reactangle( Point.Empty, Image.Size ),
new Reactangle( Point.Empty, Image.Size ),
GraphicsUnit.Pixels );
That's what I always used instead of .DrawImageUnscaled - it has failed me too many times!

A Generic error occurs at GDI+ at Bitmap.Save() after using SaveFileDialog

I use the following code block with some more code inside the using block:
using (System.Drawing.Bitmap tempImg =
(System.Drawing.Bitmap)tempObj.GetData(System.Windows.Forms.DataFormats.Bitmap))
{
// ...
tempImg.Save("..\\..\\testdata\\tempImg.bmp", ImageFormat.Bmp);
// ...
}
But I still get the error:
A Generic Error occured at GDI+
only after I make some action which is not related to the code inside the using block. In other times this works well.
Also the tempImg.bmp is a temporary file, so I delete the tempImg.bmp within the using block itself.
Since the tempImg is inside the using and this it's disposed, I think the locking problem should be solved.
Can someone please let me know what is the mistake in this code?
Edit:
System.Drawing.Image to System.Drawing.Bitmap as the type of tempImg.
Edit:
I have identified I get this error only after SaveFileDialog is created and user clicks on 'Save'.
Finally I could find what was wrong in my code and would like to mention it here as I think it may be useful to someone....
As I have given a relative path in tempImg.Save, and after the user clicks 'Save' in SaveFileDialog, the actual path for tempImg.Save become :
Path specified by SaveFileDialog + the relative path
automatically.
Thus if the path does not exist, this error occurs.
Thanks every one for the answers.
I also had once this problem- it happens because the bitmap locks and you can't save it( if you want I can find the exact explanation) so anyway a fix around is this:
Create a new bitmap the size of the original bitmap you have- copy the original bitmap to the new created bitmap and then dispose the original bitmap and save the new one.
Bitmap bm3 = new Bitmap(bm2);
And then save.
This is usually an indicator that something else, potentially some other thread in your own application, already has the target file that you're trying to save locked at the file system level. If you look at the inner exception I believe it should mention this. If it's not directly in the InnerException Another way to confirm this (or discover what it might really be instead) is to turn on first chance exceptions in the debugger and watch for what exception is being thrown "underneath" Save and then being turned into this generic exception.
Tried all the solutions given here, but in vain. Found the solution eventually.
Dispose any Graphics applied on image: g.dispose();
Make sure save path exists: System.IO.Directory.Exists(dir);
Is this an ASP.NET application?
A Generic Error occured at GDI+ in asp.net mostly because of missing target folder / access permissions.
Also your code could be simplified to :
using (Image image= dataObject.GetImage())
{
if (image != null)
{
image.Save("test.bmp");
}
}
In my case it was an ASP.NET application in which I replaced a single DLL, and I had to simply re-start the application pool after deployment. Then it worked fine.
This is code sample from Microsoft Forums.
// new image with transparent Alpha layer
using (var bitmap = new Bitmap(330, 18, PixelFormat.Format32bppArgb))
{
using (var graphics = Graphics.FromImage(bitmap))
{
// add some anti-aliasing
graphics.SmoothingMode = SmoothingMode.AntiAlias;
using (var font = new Font("Arial", 14.0f, GraphicsUnit.Pixel))
{
using (var brush = new SolidBrush(Color.White))
{
// draw it
graphics.DrawString(user.Email, font, brush, 0, 0);
}
}
}
// setup the response
Response.Clear();
Response.ContentType = "image/png";
Response.BufferOutput = true;
// write it to the output stream
bitmap.Save(Response.OutputStream, ImageFormat.Png);
Response.Flush();
}
I am trying to save image from resource and it gives me too GDI error when I directly use the method Bitmap.Save(filepath).
I think We can use the same below code for any other bitmap image by cloning it.
Private void SaveResourceImage() {
object resBmpObject = Resource.Image1.Clone();//Bitmap Image from resource file
//object resBmpObject = anyBmpImage.clone(); //for image other than resource image
Bitmap resBmpImage = (Bitmap)resBmpObject;
resBmpImage.Save(destFilePath, System.Drawing.Imaging.ImageFormat.Png);
resBmpImage.dispose();
}
Dispose your bitMap object after save image:
bitMap.Dispose()
oimg.Dispose()
bitMap = Nothing
oimg = Nothing
In my case, i was saving the bitmap file on the same location as the source,
So that's the problem.
I save the bitmap to the new location and all fine now.
I was facing the same issue, by changing image type ".bmp" to ".png" its work form me

image processing

i have some images..if these images are selected then it should generate another image which is the combination of all the selected images..
can anyone suggest as how to start with?
thanks
Use someting like that:
public void MergeImages(string FirstFileName, string SecondFileName)
{
Image firstImg = Image.FromFile(#"C:\temp\pic1.jpg");
Image secondImg = Image.FromFile(#"C:\temp\pic2.jpg");
Bitmap im1 = new Bitmap(firstImg);
Bitmap im2 = new Bitmap(secondImg);
Bitmap result = new Bitmap(im1.Width + im2.Width, (im1.Height > im2.Height) ? im1.Height : im2.Height);
Graphics gr = Graphics.FromImage(result);
gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
gr.DrawImage(firstImg, 0, 0);
gr.DrawImage(secondImg, im1.Width + 1, 0);
gr.Save();
result.Save(#"C:\test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
this code merges two images in one, systeming them into line.
i used ImageMagick to do these kind of things (http://www.imagemagick.org/Usage/layers/)
It is however a little bit different then using gdi to create images, but it is a very fast (and when you get used to the imagemagick syntax) and powerful way to edit images.
Normally you use gdi to edit images in memory; imagemagick uses a commandline utility to create images.
So for example you want to layer two images on top, you start a new process in your code in which you fire up a imagemagick proces with the right parameters and then the image is created ON DISK.
Then you can server the created image with a response.writebinary.

Categories

Resources